diff options
-rw-r--r-- | etc/nova/nova.conf.sample | 2 | ||||
-rw-r--r-- | nova/compute/api.py | 15 | ||||
-rwxr-xr-x | nova/compute/manager.py | 20 | ||||
-rw-r--r-- | nova/compute/utils.py | 34 | ||||
-rw-r--r-- | nova/conductor/manager.py | 9 | ||||
-rw-r--r-- | nova/exception.py | 29 | ||||
-rw-r--r-- | nova/manager.py | 2 | ||||
-rw-r--r-- | nova/network/floating_ips.py | 26 | ||||
-rw-r--r-- | nova/notifications.py | 49 | ||||
-rw-r--r-- | nova/notifier.py | 73 | ||||
-rw-r--r-- | nova/scheduler/driver.py | 6 | ||||
-rw-r--r-- | nova/scheduler/filter_scheduler.py | 14 | ||||
-rw-r--r-- | nova/scheduler/utils.py | 9 | ||||
-rw-r--r-- | nova/tests/compute/test_compute.py | 315 | ||||
-rw-r--r-- | nova/tests/compute/test_compute_api.py | 4 | ||||
-rw-r--r-- | nova/tests/compute/test_compute_utils.py | 85 | ||||
-rw-r--r-- | nova/tests/conductor/test_conductor.py | 27 | ||||
-rw-r--r-- | nova/tests/fake_notifier.py | 53 | ||||
-rw-r--r-- | nova/tests/scheduler/test_scheduler.py | 22 | ||||
-rw-r--r-- | nova/tests/scheduler/test_scheduler_utils.py | 18 | ||||
-rw-r--r-- | nova/tests/test_exception.py | 18 | ||||
-rw-r--r-- | nova/tests/test_notifications.py | 84 | ||||
-rw-r--r-- | nova/utils.py | 6 | ||||
-rwxr-xr-x | nova/virt/libvirt/driver.py | 11 |
24 files changed, 539 insertions, 392 deletions
diff --git a/etc/nova/nova.conf.sample b/etc/nova/nova.conf.sample index 776ec14dc8..13425f1720 100644 --- a/etc/nova/nova.conf.sample +++ b/etc/nova/nova.conf.sample @@ -260,7 +260,7 @@ #monkey_patch=false # List of modules/decorators to monkey patch (list value) -#monkey_patch_modules=nova.api.ec2.cloud:nova.openstack.common.notifier.api.notify_decorator,nova.compute.api:nova.openstack.common.notifier.api.notify_decorator +#monkey_patch_modules=nova.api.ec2.cloud:nova.notifications.notify_decorator,nova.compute.api:nova.notifications.notify_decorator # Length of generated instance admin passwords (integer value) #password_length=12 diff --git a/nova/compute/api.py b/nova/compute/api.py index e2ad1fe923..9a7f6373a9 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -50,6 +50,7 @@ from nova.network import model as network_model from nova.network.security_group import openstack_driver from nova.network.security_group import security_group_base from nova import notifications +from nova import notifier from nova.objects import aggregate as aggregate_obj from nova.objects import base as obj_base from nova.objects import instance as instance_obj @@ -62,7 +63,6 @@ from nova.objects import service as service_obj from nova.openstack.common import excutils from nova.openstack.common.gettextutils import _ from nova.openstack.common import log as logging -from nova.openstack.common.notifier import api as notifier from nova.openstack.common import strutils from nova.openstack.common import timeutils from nova.openstack.common import uuidutils @@ -75,11 +75,9 @@ from nova import volume LOG = logging.getLogger(__name__) - -wrap_exception = functools.partial( - exception.wrap_exception, - notifier=notifier, publisher_id=notifier.publisher_id('aggregate')) - +get_notifier = functools.partial(notifier.get_notifier, service='aggregate') +wrap_exception = functools.partial(exception.wrap_exception, + get_notifier=get_notifier) compute_opts = [ cfg.BoolOpt('allow_resize_to_same_host', @@ -236,6 +234,7 @@ class API(base.Base): self.compute_rpcapi = compute_rpcapi.ComputeAPI() self._compute_task_api = None self.servicegroup_api = servicegroup.API() + self.notifier = notifier.get_notifier('compute', CONF.host) super(API, self).__init__(**kwargs) @@ -1418,7 +1417,7 @@ class API(base.Base): instance_uuid = instance['uuid'] instance.info_cache.delete() compute_utils.notify_about_instance_usage( - context, instance, "%s.start" % delete_type) + self.notifier, context, instance, "%s.start" % delete_type) elevated = context.elevated() if self.cell_type != 'api': @@ -1445,7 +1444,7 @@ class API(base.Base): cb(context, instance, bdms, local=True) instance.destroy() compute_utils.notify_about_instance_usage( - context, instance, "%s.end" % delete_type, + self.notifier, context, instance, "%s.end" % delete_type, system_metadata=system_meta) def _do_delete(self, context, instance, bdms, reservations=None, diff --git a/nova/compute/manager.py b/nova/compute/manager.py index 9c9e307e89..722f90f38c 100755 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -60,6 +60,7 @@ from nova import manager from nova import network from nova.network import model as network_model from nova.network.security_group import openstack_driver +from nova import notifier from nova.objects import base as obj_base from nova.objects import instance as instance_obj from nova.objects import migration as migration_obj @@ -67,7 +68,6 @@ from nova.openstack.common import excutils from nova.openstack.common.gettextutils import _ 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 periodic_task from nova.openstack.common import rpc from nova.openstack.common.rpc import common as rpc_common @@ -214,10 +214,9 @@ CONF.import_opt('enable', 'nova.cells.opts', group='cells') LOG = logging.getLogger(__name__) - -wrap_exception = functools.partial( - exception.wrap_exception, - notifier=notifier, publisher_id=notifier.publisher_id('compute')) +get_notifier = functools.partial(notifier.get_notifier, service='compute') +wrap_exception = functools.partial(exception.wrap_exception, + get_notifier=get_notifier) def reverts_task_state(function): @@ -1364,14 +1363,11 @@ class ComputeManager(manager.SchedulerDependentManager): def _notify_about_instance_usage(self, context, instance, event_suffix, network_info=None, system_metadata=None, extra_usage_info=None): - # NOTE(sirp): The only thing this wrapper function does extra is handle - # the passing in of `self.host`. Ordinarily this will just be - # CONF.host`, but `Manager`'s gets a chance to override this in its - # `__init__`. compute_utils.notify_about_instance_usage( - context, instance, event_suffix, network_info=network_info, - system_metadata=system_metadata, - extra_usage_info=extra_usage_info, host=self.host) + self.notifier, context, instance, event_suffix, + network_info=network_info, + system_metadata=system_metadata, + extra_usage_info=extra_usage_info) def _deallocate_network(self, context, instance, requested_networks=None): diff --git a/nova/compute/utils.py b/nova/compute/utils.py index fb2ab6d200..f63da1b661 100644 --- a/nova/compute/utils.py +++ b/nova/compute/utils.py @@ -27,10 +27,10 @@ from nova.compute import flavors from nova import exception from nova.network import model as network_model from nova import notifications +from nova import notifier as notify from nova.objects import instance as instance_obj from nova.openstack.common.gettextutils import _ 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 from nova.virt import driver @@ -191,12 +191,14 @@ def _get_unused_letter(used_letters): return letters[0] -def notify_usage_exists(context, instance_ref, current_period=False, +def notify_usage_exists(notifier, context, instance_ref, current_period=False, ignore_missing_network_data=True, system_metadata=None, extra_usage_info=None): """Generates 'exists' notification for an instance for usage auditing purposes. + :param notifier: a messaging.Notifier + :param current_period: if True, this will generate a usage for the current usage period; if False, this will generate a usage for the previous audit period. @@ -228,29 +230,24 @@ def notify_usage_exists(context, instance_ref, current_period=False, if extra_usage_info: extra_info.update(extra_usage_info) - notify_about_instance_usage(context, instance_ref, 'exists', + notify_about_instance_usage(notifier, context, instance_ref, 'exists', system_metadata=system_metadata, extra_usage_info=extra_info) -def notify_about_instance_usage(context, instance, event_suffix, +def notify_about_instance_usage(notifier, context, instance, event_suffix, network_info=None, system_metadata=None, - extra_usage_info=None, host=None): + extra_usage_info=None): """ Send a notification about an instance. + :param notifier: a messaging.Notifier :param event_suffix: Event type like "delete.start" or "exists" :param network_info: Networking information, if provided. :param system_metadata: system_metadata DB entries for the instance, if provided. :param extra_usage_info: Dictionary containing extra values to add or override in the notification. - :param host: Compute host for the instance, if specified. Default is - CONF.host """ - - if not host: - host = CONF.host - if not extra_usage_info: extra_usage_info = {} @@ -258,13 +255,11 @@ def notify_about_instance_usage(context, instance, event_suffix, network_info, system_metadata, **extra_usage_info) if event_suffix.endswith("error"): - level = notifier_api.ERROR + method = notifier.error else: - level = notifier_api.INFO + method = notifier.info - notifier_api.notify(context, 'compute.%s' % host, - 'compute.instance.%s' % event_suffix, level, - usage_info) + method(context, 'compute.instance.%s' % event_suffix, usage_info) def notify_about_aggregate_update(context, event_suffix, aggregate_payload): @@ -282,9 +277,10 @@ def notify_about_aggregate_update(context, event_suffix, aggregate_payload): "notification and it will be ignored")) return - notifier_api.notify(context, 'aggregate.%s' % aggregate_identifier, - 'aggregate.%s' % event_suffix, notifier_api.INFO, - aggregate_payload) + notifier = notify.get_notifier(service='aggregate', + host=aggregate_identifier) + + notifier.info(context, 'aggregate.%s' % event_suffix, aggregate_payload) def get_nw_info_for_instance(instance): diff --git a/nova/conductor/manager.py b/nova/conductor/manager.py index 5badd443c9..e2dab2803c 100644 --- a/nova/conductor/manager.py +++ b/nova/conductor/manager.py @@ -39,7 +39,6 @@ from nova.openstack.common import excutils from nova.openstack.common.gettextutils import _ 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.rpc import common as rpc_common from nova.openstack.common import timeutils from nova import quota @@ -401,9 +400,8 @@ class ConductorManager(manager.Manager): update_totals) # We have just updated the database, so send the notification now - notifier.notify(context, 'conductor.%s' % self.host, 'volume.usage', - notifier.INFO, - compute_utils.usage_volume_info(vol_usage)) + self.notifier.info(context, 'volume.usage', + compute_utils.usage_volume_info(vol_usage)) @rpc_common.client_exceptions(exception.ComputeHostNotFound, exception.HostBinaryNotFound) @@ -482,7 +480,8 @@ class ConductorManager(manager.Manager): def notify_usage_exists(self, context, instance, current_period=False, ignore_missing_network_data=True, system_metadata=None, extra_usage_info=None): - compute_utils.notify_usage_exists(context, instance, current_period, + compute_utils.notify_usage_exists(self.notifier, context, instance, + current_period, ignore_missing_network_data, system_metadata, extra_usage_info) diff --git a/nova/exception.py b/nova/exception.py index 04fdec112b..07917b37dd 100644 --- a/nova/exception.py +++ b/nova/exception.py @@ -60,14 +60,11 @@ def _cleanse_dict(original): return dict((k, v) for k, v in original.iteritems() if not "_pass" in k) -def wrap_exception(notifier, publisher_id): +def wrap_exception(notifier=None, get_notifier=None): """This decorator wraps a method to catch any exceptions that may get thrown. It logs the exception as well as optionally sending it to the notification system. """ - # TODO(sandy): Find a way to import nova.notifier.api so we don't have - # to pass it in as a parameter. Otherwise we get a cyclic import of - # nova.notifier.api -> nova.utils -> nova.exception :( def inner(f): def wrapped(self, context, *args, **kw): # Don't store self or context in the payload, it now seems to @@ -76,16 +73,20 @@ def wrap_exception(notifier, publisher_id): return f(self, context, *args, **kw) except Exception as e: with excutils.save_and_reraise_exception(): - payload = dict(exception=e) - call_dict = safe_utils.getcallargs(f, *args, **kw) - cleansed = _cleanse_dict(call_dict) - payload.update({'args': cleansed}) - - level = notifier.ERROR - event_type = f.__name__ - - notifier.notify(context, publisher_id, - event_type, level, payload) + if notifier or get_notifier: + payload = dict(exception=e) + call_dict = safe_utils.getcallargs(f, *args, **kw) + cleansed = _cleanse_dict(call_dict) + payload.update({'args': cleansed}) + + # If f has multiple decorators, they must use + # functools.wraps to ensure the name is + # propagated. + event_type = f.__name__ + + (notifier or get_notifier()).error(context, + event_type, + payload) return functools.wraps(f)(wrapped) return inner diff --git a/nova/manager.py b/nova/manager.py index a270b927b7..68c8f9449d 100644 --- a/nova/manager.py +++ b/nova/manager.py @@ -57,6 +57,7 @@ from oslo.config import cfg from nova import baserpc from nova.db import base +from nova import notifier from nova.objects import base as objects_base from nova.openstack.common.gettextutils import _ from nova.openstack.common import log as logging @@ -80,6 +81,7 @@ class Manager(base.Base, periodic_task.PeriodicTasks): self.host = host self.backdoor_port = None self.service_name = service_name + self.notifier = notifier.get_notifier(self.service_name, self.host) super(Manager, self).__init__(db_driver) def create_rpc_dispatcher(self, backdoor_port=None, additional_apis=None): diff --git a/nova/network/floating_ips.py b/nova/network/floating_ips.py index b5e4aecc07..2fbaa0647d 100644 --- a/nova/network/floating_ips.py +++ b/nova/network/floating_ips.py @@ -23,11 +23,11 @@ from nova import context from nova.db import base from nova import exception from nova.network import rpcapi as network_rpcapi +from nova import notifier from nova.openstack.common import excutils from nova.openstack.common.gettextutils import _ 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.openstack.common import processutils from nova.openstack.common.rpc import common as rpc_common from nova.openstack.common import uuidutils @@ -224,10 +224,8 @@ class FloatingIP(object): floating_ip = self.db.floating_ip_allocate_address( context, project_id, pool, auto_assigned=auto_assigned) payload = dict(project_id=project_id, floating_ip=floating_ip) - notifier.notify(context, - notifier.publisher_id("network"), - 'network.floating_ip.allocate', - notifier.INFO, payload) + self.notifier.info(context, + 'network.floating_ip.allocate', payload) # Commit the reservations if use_quota: @@ -263,10 +261,7 @@ class FloatingIP(object): floating_ip['address']) payload = dict(project_id=floating_ip['project_id'], floating_ip=floating_ip['address']) - notifier.notify(context, - notifier.publisher_id("network"), - 'network.floating_ip.deallocate', - notifier.INFO, payload=payload) + self.notifier.info(context, 'network.floating_ip.deallocate', payload) # Get reservations... try: @@ -375,10 +370,8 @@ class FloatingIP(object): payload = dict(project_id=context.project_id, instance_id=instance_uuid, floating_ip=floating_address) - notifier.notify(context, - notifier.publisher_id("network"), - 'network.floating_ip.associate', - notifier.INFO, payload=payload) + self.notifier.info(context, + 'network.floating_ip.associate', payload) do_associate() @rpc_common.client_exceptions(exception.FloatingIpNotFoundForAddress) @@ -461,10 +454,8 @@ class FloatingIP(object): payload = dict(project_id=context.project_id, instance_id=instance_uuid, floating_ip=address) - notifier.notify(context, - notifier.publisher_id("network"), - 'network.floating_ip.disassociate', - notifier.INFO, payload=payload) + self.notifier.info(context, + 'network.floating_ip.disassociate', payload) do_disassociate() @rpc_common.client_exceptions(exception.FloatingIpNotFound) @@ -699,3 +690,4 @@ class LocalManager(base.Base, FloatingIP): CONF.floating_ip_dns_manager) self.instance_dns_manager = importutils.import_object( CONF.instance_dns_manager) + self.notifier = notifier.get_notifier('network', CONF.host) diff --git a/nova/notifications.py b/nova/notifications.py index aefd1fa82a..fe0dd73904 100644 --- a/nova/notifications.py +++ b/nova/notifications.py @@ -2,6 +2,7 @@ # Copyright (c) 2012 OpenStack Foundation # All Rights Reserved. +# Copyright 2013 Red Hat, Inc. # # 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 @@ -29,10 +30,11 @@ from nova import db from nova.image import glance from nova import network from nova.network import model as network_model +from nova import notifier as notify +from nova.openstack.common import context as common_context from nova.openstack.common import excutils from nova.openstack.common.gettextutils import _ 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 @@ -53,6 +55,40 @@ notify_opts = [ CONF = cfg.CONF CONF.register_opts(notify_opts) +CONF.import_opt('default_notification_level', + 'nova.openstack.common.notifier.api') +CONF.import_opt('default_publisher_id', + 'nova.openstack.common.notifier.api') + + +def notify_decorator(name, fn): + """Decorator for notify which is used from utils.monkey_patch(). + + :param name: name of the function + :param function: - object of the function + :returns: function -- decorated function + + """ + def wrapped_func(*args, **kwarg): + body = {} + body['args'] = [] + body['kwarg'] = {} + for arg in args: + body['args'].append(arg) + for key in kwarg: + body['kwarg'][key] = kwarg[key] + + ctxt = common_context.get_context_from_function_and_args( + fn, args, kwarg) + + notifier = notify.get_notifier(publisher_id=(CONF.default_publisher_id + or CONF.host)) + method = notifier.getattr(CONF.default_notification_level.lower(), + 'info') + method(ctxt, name, body) + + return fn(*args, **kwarg) + return wrapped_func def send_api_fault(url, status, exception): @@ -63,10 +99,7 @@ def send_api_fault(url, status, exception): payload = {'url': url, 'exception': str(exception), 'status': status} - publisher_id = notifier_api.publisher_id("api") - - notifier_api.notify(None, publisher_id, 'api.fault', notifier_api.ERROR, - payload) + notify.get_notifier('api').error(None, 'api.fault', payload) def send_update(context, old_instance, new_instance, service=None, host=None): @@ -192,10 +225,8 @@ def _send_instance_update_notification(context, instance, old_vm_state=None, if old_display_name: payload["old_display_name"] = old_display_name - publisher_id = notifier_api.publisher_id(service, host) - - notifier_api.notify(context, publisher_id, 'compute.instance.update', - notifier_api.INFO, payload) + notify.get_notifier(service, host).info(context, + 'compute.instance.update', payload) def audit_period_bounds(current_period=False): diff --git a/nova/notifier.py b/nova/notifier.py new file mode 100644 index 0000000000..165dcaa084 --- /dev/null +++ b/nova/notifier.py @@ -0,0 +1,73 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2013 Red Hat, Inc. +# +# 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. + +""" +A temporary helper which emulates oslo.messaging.Notifier. + +This helper method allows us to do the tedious porting to the new Notifier API +as a standalone commit so that the commit which switches us to oslo.messaging +is smaller and easier to review. This file will be removed as part of that +commit. +""" + +from oslo.config import cfg + +from nova.openstack.common.notifier import api as notifier_api + +CONF = cfg.CONF + + +class Notifier(object): + + def __init__(self, publisher_id): + super(Notifier, self).__init__() + self.publisher_id = publisher_id + + _marker = object() + + def prepare(self, publisher_id=_marker): + ret = self.__class__(self.publisher_id) + if publisher_id is not self._marker: + ret.publisher_id = publisher_id + return ret + + def _notify(self, ctxt, event_type, payload, priority): + notifier_api.notify(ctxt, + self.publisher_id, + event_type, + priority, + payload) + + def debug(self, ctxt, event_type, payload): + self._notify(ctxt, event_type, payload, 'DEBUG') + + def info(self, ctxt, event_type, payload): + self._notify(ctxt, event_type, payload, 'INFO') + + def warn(self, ctxt, event_type, payload): + self._notify(ctxt, event_type, payload, 'WARN') + + def error(self, ctxt, event_type, payload): + self._notify(ctxt, event_type, payload, 'ERROR') + + def critical(self, ctxt, event_type, payload): + self._notify(ctxt, event_type, payload, 'CRITICAL') + + +def get_notifier(service=None, host=None, publisher_id=None): + if not publisher_id: + publisher_id = "%s.%s" % (service, host or CONF.host) + return Notifier(publisher_id) diff --git a/nova/scheduler/driver.py b/nova/scheduler/driver.py index 87ac3f5dad..e86db9d139 100644 --- a/nova/scheduler/driver.py +++ b/nova/scheduler/driver.py @@ -31,10 +31,10 @@ from nova.conductor import api as conductor_api from nova import db from nova import exception from nova import notifications +from nova import notifier from nova.openstack.common.gettextutils import _ 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.openstack.common import timeutils from nova import servicegroup @@ -78,8 +78,8 @@ def handle_schedule_error(context, ex, instance_uuid, request_spec): method='run_instance', reason=ex) - notifier.notify(context, notifier.publisher_id("scheduler"), - 'scheduler.run_instance', notifier.ERROR, payload) + notifier.get_notifier('scheduler').error(context, + 'scheduler.run_instance', payload) def instance_update_db(context, instance_uuid, extra_values=None): diff --git a/nova/scheduler/filter_scheduler.py b/nova/scheduler/filter_scheduler.py index f9c15c106a..d5f2848efd 100644 --- a/nova/scheduler/filter_scheduler.py +++ b/nova/scheduler/filter_scheduler.py @@ -27,9 +27,9 @@ from nova.compute import flavors from nova.compute import rpcapi as compute_rpcapi from nova import db from nova import exception +from nova import notifier from nova.openstack.common.gettextutils import _ from nova.openstack.common import log as logging -from nova.openstack.common.notifier import api as notifier from nova.pci import pci_request from nova.scheduler import driver from nova.scheduler import scheduler_options @@ -61,6 +61,7 @@ class FilterScheduler(driver.Scheduler): super(FilterScheduler, self).__init__(*args, **kwargs) self.options = scheduler_options.SchedulerOptions() self.compute_rpcapi = compute_rpcapi.ComputeAPI() + self.notifier = notifier.get_notifier('scheduler') def schedule_run_instance(self, context, request_spec, admin_password, injected_files, @@ -73,8 +74,7 @@ class FilterScheduler(driver.Scheduler): Returns a list of the instances created. """ payload = dict(request_spec=request_spec) - notifier.notify(context, notifier.publisher_id("scheduler"), - 'scheduler.run_instance.start', notifier.INFO, payload) + self.notifier.info(context, 'scheduler.run_instance.start', payload) instance_uuids = request_spec.get('instance_uuids') LOG.info(_("Attempting to build %(num_instances)d instance(s) " @@ -127,8 +127,7 @@ class FilterScheduler(driver.Scheduler): retry = filter_properties.get('retry', {}) retry['hosts'] = [] - notifier.notify(context, notifier.publisher_id("scheduler"), - 'scheduler.run_instance.end', notifier.INFO, payload) + self.notifier.info(context, 'scheduler.run_instance.end', payload) def select_hosts(self, context, request_spec, filter_properties): """Selects a filtered set of hosts.""" @@ -164,9 +163,8 @@ class FilterScheduler(driver.Scheduler): payload = dict(request_spec=request_spec, weighted_host=weighed_host.to_dict(), instance_id=instance_uuid) - notifier.notify(context, notifier.publisher_id("scheduler"), - 'scheduler.run_instance.scheduled', notifier.INFO, - payload) + self.notifier.info(context, + 'scheduler.run_instance.scheduled', payload) # Update the metadata if necessary scheduler_hints = filter_properties.get('scheduler_hints') or {} diff --git a/nova/scheduler/utils.py b/nova/scheduler/utils.py index 1a436d3072..93aec54b15 100644 --- a/nova/scheduler/utils.py +++ b/nova/scheduler/utils.py @@ -20,10 +20,10 @@ from nova.compute import flavors from nova.compute import utils as compute_utils from nova import db from nova import notifications +from nova import notifier as notify from nova.openstack.common.gettextutils import _ from nova.openstack.common import jsonutils from nova.openstack.common import log as logging -from nova.openstack.common.notifier import api as notifier LOG = logging.getLogger(__name__) @@ -69,6 +69,8 @@ def set_vm_state_and_notify(context, service, method, updates, ex, # verify that uuid is always set. uuids = [properties.get('uuid')] from nova.conductor import api as conductor_api + conductor = conductor_api.LocalAPI() + notifier = notify.get_notifier(service) for instance_uuid in request_spec.get('instance_uuids') or uuids: if instance_uuid: state = vm_state.upper() @@ -81,7 +83,7 @@ def set_vm_state_and_notify(context, service, method, updates, ex, notifications.send_update(context, old_ref, new_ref, service=service) compute_utils.add_instance_fault_from_exc(context, - conductor_api.LocalAPI(), + conductor, new_ref, ex, sys.exc_info()) payload = dict(request_spec=request_spec, @@ -92,8 +94,7 @@ def set_vm_state_and_notify(context, service, method, updates, ex, reason=ex) event_type = '%s.%s' % (service, method) - notifier.notify(context, notifier.publisher_id(service), - event_type, notifier.ERROR, payload) + notifier.error(context, event_type, payload) def populate_filter_properties(filter_properties, host_state): diff --git a/nova/tests/compute/test_compute.py b/nova/tests/compute/test_compute.py index f2d1ae1851..2b4c2cf4d9 100644 --- a/nova/tests/compute/test_compute.py +++ b/nova/tests/compute/test_compute.py @@ -4,6 +4,7 @@ # Administrator of the National Aeronautics and Space Administration. # Copyright 2011 Piston Cloud Computing, Inc. # All Rights Reserved. +# Copyright 2013 Red Hat, Inc. # # 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 @@ -60,8 +61,6 @@ from nova.openstack.common.gettextutils import _ 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_api -from nova.openstack.common.notifier import test_notifier from nova.openstack.common import rpc from nova.openstack.common.rpc import common as rpc_common from nova.openstack.common import timeutils @@ -75,6 +74,7 @@ from nova.tests import fake_instance from nova.tests import fake_instance_actions from nova.tests import fake_network from nova.tests import fake_network_cache_model +from nova.tests import fake_notifier from nova.tests.image import fake as fake_image from nova.tests import matchers from nova.tests.objects import test_migration @@ -147,13 +147,14 @@ class BaseTestCase(test.TestCase): def setUp(self): super(BaseTestCase, self).setUp() - notifier_api._reset_drivers() - self.addCleanup(notifier_api._reset_drivers) self.flags(compute_driver='nova.virt.fake.FakeDriver', - notification_driver=[test_notifier.__name__], network_manager='nova.network.manager.FlatManager') fake.set_nodes([NODENAME]) self.flags(use_local=True, group='conductor') + + fake_notifier.stub_notifier(self.stubs) + self.addCleanup(fake_notifier.reset) + self.compute = importutils.import_object(CONF.compute_manager) # override tracker with a version that doesn't need the database: @@ -201,7 +202,6 @@ class BaseTestCase(test.TestCase): self.project_id = 'fake' self.context = context.RequestContext(self.user_id, self.project_id) - test_notifier.NOTIFICATIONS = [] def fake_show(meh, context, id): if id: @@ -581,19 +581,18 @@ class ComputeVolumeTestCase(BaseTestCase): CONF.volume_usage_poll_interval = 10 self.compute._poll_volume_usage(self.context) # Check that a volume.usage and volume.attach notification was sent - self.assertEqual(2, len(test_notifier.NOTIFICATIONS)) - msg = test_notifier.NOTIFICATIONS[0] + self.assertEqual(2, len(fake_notifier.NOTIFICATIONS)) self.compute.detach_volume(self.context, 1, instance) # Check that volume.attach, 2 volume.usage, and volume.detach # notifications were sent - self.assertEquals(4, len(test_notifier.NOTIFICATIONS)) - msg = test_notifier.NOTIFICATIONS[0] - self.assertEquals('compute.instance.volume.attach', msg['event_type']) - msg = test_notifier.NOTIFICATIONS[2] - self.assertEquals('volume.usage', msg['event_type']) - payload = msg['payload'] + self.assertEquals(4, len(fake_notifier.NOTIFICATIONS)) + msg = fake_notifier.NOTIFICATIONS[0] + self.assertEquals('compute.instance.volume.attach', msg.event_type) + msg = fake_notifier.NOTIFICATIONS[2] + self.assertEquals('volume.usage', msg.event_type) + payload = msg.payload self.assertEquals(instance['uuid'], payload['instance_id']) self.assertEquals('fake', payload['user_id']) self.assertEquals('fake', payload['tenant_id']) @@ -602,8 +601,8 @@ class ComputeVolumeTestCase(BaseTestCase): self.assertEquals(1, payload['writes']) self.assertEquals(20, payload['write_bytes']) self.assertEquals(None, payload['availability_zone']) - msg = test_notifier.NOTIFICATIONS[3] - self.assertEquals('compute.instance.volume.detach', msg['event_type']) + msg = fake_notifier.NOTIFICATIONS[3] + self.assertEquals('compute.instance.volume.detach', msg.event_type) # Check the database for the volume_usages = db.vol_get_usage_by_time(self.context, 0) @@ -2601,11 +2600,11 @@ class ComputeTestCase(BaseTestCase): instance = jsonutils.to_primitive(self._create_fake_instance()) - self.assertEquals(len(test_notifier.NOTIFICATIONS), 0) + self.assertEquals(len(fake_notifier.NOTIFICATIONS), 0) self.compute.add_fixed_ip_to_instance(self.context, network_id=1, instance=instance) - self.assertEquals(len(test_notifier.NOTIFICATIONS), 2) + self.assertEquals(len(fake_notifier.NOTIFICATIONS), 2) self.compute.terminate_instance(self.context, instance=instance) def test_remove_fixed_ip_usage_notification(self): @@ -2621,11 +2620,11 @@ class ComputeTestCase(BaseTestCase): instance = jsonutils.to_primitive(self._create_fake_instance()) - self.assertEquals(len(test_notifier.NOTIFICATIONS), 0) + self.assertEquals(len(fake_notifier.NOTIFICATIONS), 0) self.compute.remove_fixed_ip_from_instance(self.context, 1, instance=instance) - self.assertEquals(len(test_notifier.NOTIFICATIONS), 2) + self.assertEquals(len(fake_notifier.NOTIFICATIONS), 2) self.compute.terminate_instance(self.context, instance=instance) def test_run_instance_usage_notification(self): @@ -2633,16 +2632,16 @@ class ComputeTestCase(BaseTestCase): instance = jsonutils.to_primitive(self._create_fake_instance()) instance_uuid = instance['uuid'] self.compute.run_instance(self.context, instance=instance) - self.assertEquals(len(test_notifier.NOTIFICATIONS), 2) + self.assertEquals(len(fake_notifier.NOTIFICATIONS), 2) inst_ref = db.instance_get_by_uuid(self.context, instance_uuid) - msg = test_notifier.NOTIFICATIONS[0] - self.assertEquals(msg['event_type'], 'compute.instance.create.start') - self.assertEquals(msg['payload']['image_name'], 'fake_name') + msg = fake_notifier.NOTIFICATIONS[0] + self.assertEquals(msg.event_type, 'compute.instance.create.start') + self.assertEquals(msg.payload['image_name'], 'fake_name') # The last event is the one with the sugar in it. - msg = test_notifier.NOTIFICATIONS[1] - self.assertEquals(msg['priority'], 'INFO') - self.assertEquals(msg['event_type'], 'compute.instance.create.end') - payload = msg['payload'] + msg = fake_notifier.NOTIFICATIONS[1] + self.assertEquals(msg.priority, 'INFO') + self.assertEquals(msg.event_type, 'compute.instance.create.end') + payload = msg.payload self.assertEquals(payload['tenant_id'], self.project_id) self.assertEquals(payload['image_name'], 'fake_name') self.assertEquals(payload['user_id'], self.user_id) @@ -2674,14 +2673,14 @@ class ComputeTestCase(BaseTestCase): self.stubs.Set(self.compute, '_build_instance', build_inst_abort) self.compute.run_instance(self.context, instance=instance) - self.assertEquals(len(test_notifier.NOTIFICATIONS), 2) - msg = test_notifier.NOTIFICATIONS[0] - self.assertEquals(msg['event_type'], 'compute.instance.create.start') - msg = test_notifier.NOTIFICATIONS[1] - - self.assertEquals(msg['event_type'], 'compute.instance.create.end') - self.assertEquals('INFO', msg['priority']) - payload = msg['payload'] + self.assertEquals(len(fake_notifier.NOTIFICATIONS), 2) + msg = fake_notifier.NOTIFICATIONS[0] + self.assertEquals(msg.event_type, 'compute.instance.create.start') + msg = fake_notifier.NOTIFICATIONS[1] + + self.assertEquals(msg.event_type, 'compute.instance.create.end') + self.assertEquals('INFO', msg.priority) + payload = msg.payload message = payload['message'] self.assertTrue(message.find("already deleted") != -1) @@ -2698,14 +2697,14 @@ class ComputeTestCase(BaseTestCase): self.compute.run_instance(self.context, instance=instance) - self.assertTrue(len(test_notifier.NOTIFICATIONS) >= 2) - msg = test_notifier.NOTIFICATIONS[0] - self.assertEquals(msg['event_type'], 'compute.instance.create.start') - msg = test_notifier.NOTIFICATIONS[1] + self.assertTrue(len(fake_notifier.NOTIFICATIONS) >= 2) + msg = fake_notifier.NOTIFICATIONS[0] + self.assertEquals(msg.event_type, 'compute.instance.create.start') + msg = fake_notifier.NOTIFICATIONS[1] - self.assertEquals(msg['event_type'], 'compute.instance.create.error') - self.assertEquals('ERROR', msg['priority']) - payload = msg['payload'] + self.assertEquals(msg.event_type, 'compute.instance.create.error') + self.assertEquals('ERROR', msg.priority) + payload = msg.payload message = payload['message'] self.assertTrue(message.find("something bad happened") != -1) @@ -2722,14 +2721,14 @@ class ComputeTestCase(BaseTestCase): self.assertRaises(test.TestingException, self.compute.run_instance, self.context, instance=instance) - self.assertTrue(len(test_notifier.NOTIFICATIONS) >= 2) - msg = test_notifier.NOTIFICATIONS[0] - self.assertEquals(msg['event_type'], 'compute.instance.create.start') - msg = test_notifier.NOTIFICATIONS[1] + self.assertTrue(len(fake_notifier.NOTIFICATIONS) >= 2) + msg = fake_notifier.NOTIFICATIONS[0] + self.assertEquals(msg.event_type, 'compute.instance.create.start') + msg = fake_notifier.NOTIFICATIONS[1] - self.assertEquals(msg['event_type'], 'compute.instance.create.error') - self.assertEquals('ERROR', msg['priority']) - payload = msg['payload'] + self.assertEquals(msg.event_type, 'compute.instance.create.error') + self.assertEquals('ERROR', msg.priority) + payload = msg.payload message = payload['message'] self.assertTrue(message.find("i'm dying") != -1) @@ -2741,23 +2740,22 @@ class ComputeTestCase(BaseTestCase): instance = jsonutils.to_primitive(self._create_fake_instance()) self.compute.run_instance(self.context, instance=instance) - test_notifier.NOTIFICATIONS = [] + fake_notifier.NOTIFICATIONS = [] timeutils.set_time_override(cur_time) self.compute.terminate_instance(self.context, instance=instance) - self.assertEquals(len(test_notifier.NOTIFICATIONS), 4) - - msg = test_notifier.NOTIFICATIONS[0] - self.assertEquals(msg['priority'], 'INFO') - self.assertEquals(msg['event_type'], 'compute.instance.delete.start') - msg1 = test_notifier.NOTIFICATIONS[1] - self.assertEquals(msg1['event_type'], - 'compute.instance.shutdown.start') - msg1 = test_notifier.NOTIFICATIONS[2] - self.assertEquals(msg1['event_type'], 'compute.instance.shutdown.end') - msg1 = test_notifier.NOTIFICATIONS[3] - self.assertEquals(msg1['event_type'], 'compute.instance.delete.end') - payload = msg1['payload'] + self.assertEquals(len(fake_notifier.NOTIFICATIONS), 4) + + msg = fake_notifier.NOTIFICATIONS[0] + self.assertEquals(msg.priority, 'INFO') + self.assertEquals(msg.event_type, 'compute.instance.delete.start') + msg1 = fake_notifier.NOTIFICATIONS[1] + self.assertEquals(msg1.event_type, 'compute.instance.shutdown.start') + msg1 = fake_notifier.NOTIFICATIONS[2] + self.assertEquals(msg1.event_type, 'compute.instance.shutdown.end') + msg1 = fake_notifier.NOTIFICATIONS[3] + self.assertEquals(msg1.event_type, 'compute.instance.delete.end') + payload = msg1.payload self.assertEquals(payload['tenant_id'], self.project_id) self.assertEquals(payload['user_id'], self.user_id) self.assertEquals(payload['instance_id'], instance['uuid']) @@ -3502,7 +3500,7 @@ class ComputeTestCase(BaseTestCase): self.compute.run_instance(self.context, instance=inst_ref) timeutils.set_time_override(cur_time) - test_notifier.NOTIFICATIONS = [] + fake_notifier.NOTIFICATIONS = [] instance = db.instance_get_by_uuid(self.context, inst_ref['uuid']) orig_sys_metadata = db.instance_system_metadata_get(self.context, inst_ref['uuid']) @@ -3530,21 +3528,21 @@ class ComputeTestCase(BaseTestCase): image_ref_url = glance.generate_image_url(image_ref) new_image_ref_url = glance.generate_image_url(new_image_ref) - self.assertEquals(len(test_notifier.NOTIFICATIONS), 3) - msg = test_notifier.NOTIFICATIONS[0] - self.assertEquals(msg['event_type'], + self.assertEquals(len(fake_notifier.NOTIFICATIONS), 3) + msg = fake_notifier.NOTIFICATIONS[0] + self.assertEquals(msg.event_type, 'compute.instance.exists') - self.assertEquals(msg['payload']['image_ref_url'], image_ref_url) - msg = test_notifier.NOTIFICATIONS[1] - self.assertEquals(msg['event_type'], + self.assertEquals(msg.payload['image_ref_url'], image_ref_url) + msg = fake_notifier.NOTIFICATIONS[1] + self.assertEquals(msg.event_type, 'compute.instance.rebuild.start') - self.assertEquals(msg['payload']['image_ref_url'], new_image_ref_url) - self.assertEquals(msg['payload']['image_name'], 'fake_name') - msg = test_notifier.NOTIFICATIONS[2] - self.assertEquals(msg['event_type'], + self.assertEquals(msg.payload['image_ref_url'], new_image_ref_url) + self.assertEquals(msg.payload['image_name'], 'fake_name') + msg = fake_notifier.NOTIFICATIONS[2] + self.assertEquals(msg.event_type, 'compute.instance.rebuild.end') - self.assertEquals(msg['priority'], 'INFO') - payload = msg['payload'] + self.assertEquals(msg.priority, 'INFO') + payload = msg.payload self.assertEquals(payload['image_name'], 'fake_name') self.assertEquals(payload['tenant_id'], self.project_id) self.assertEquals(payload['user_id'], self.user_id) @@ -3587,7 +3585,7 @@ class ComputeTestCase(BaseTestCase): self.compute.resize_instance(self.context, instance=instance, migration=migration, image={}, instance_type=new_type) timeutils.set_time_override(cur_time) - test_notifier.NOTIFICATIONS = [] + fake_notifier.NOTIFICATIONS = [] instance_p = obj_base.obj_to_primitive(instance) migration_p = obj_base.obj_to_primitive(migration) @@ -3595,15 +3593,15 @@ class ComputeTestCase(BaseTestCase): migration=migration_p, disk_info={}, image={}, instance=instance_p) - self.assertEquals(len(test_notifier.NOTIFICATIONS), 2) - msg = test_notifier.NOTIFICATIONS[0] - self.assertEquals(msg['event_type'], + self.assertEquals(len(fake_notifier.NOTIFICATIONS), 2) + msg = fake_notifier.NOTIFICATIONS[0] + self.assertEquals(msg.event_type, 'compute.instance.finish_resize.start') - msg = test_notifier.NOTIFICATIONS[1] - self.assertEquals(msg['event_type'], + msg = fake_notifier.NOTIFICATIONS[1] + self.assertEquals(msg.event_type, 'compute.instance.finish_resize.end') - self.assertEquals(msg['priority'], 'INFO') - payload = msg['payload'] + self.assertEquals(msg.priority, 'INFO') + payload = msg.payload self.assertEquals(payload['tenant_id'], self.project_id) self.assertEquals(payload['user_id'], self.user_id) self.assertEquals(payload['instance_id'], instance.uuid) @@ -3627,7 +3625,7 @@ class ComputeTestCase(BaseTestCase): self.compute.run_instance(self.context, instance=instance) timeutils.set_time_override(cur_time) - test_notifier.NOTIFICATIONS = [] + fake_notifier.NOTIFICATIONS = [] instance.host = 'foo' instance.task_state = task_states.RESIZE_PREP @@ -3640,18 +3638,18 @@ class ComputeTestCase(BaseTestCase): instance.uuid, 'pre-migrating') - self.assertEquals(len(test_notifier.NOTIFICATIONS), 3) - msg = test_notifier.NOTIFICATIONS[0] - self.assertEquals(msg['event_type'], + self.assertEquals(len(fake_notifier.NOTIFICATIONS), 3) + msg = fake_notifier.NOTIFICATIONS[0] + self.assertEquals(msg.event_type, 'compute.instance.exists') - msg = test_notifier.NOTIFICATIONS[1] - self.assertEquals(msg['event_type'], + msg = fake_notifier.NOTIFICATIONS[1] + self.assertEquals(msg.event_type, 'compute.instance.resize.prep.start') - msg = test_notifier.NOTIFICATIONS[2] - self.assertEquals(msg['event_type'], + msg = fake_notifier.NOTIFICATIONS[2] + self.assertEquals(msg.event_type, 'compute.instance.resize.prep.end') - self.assertEquals(msg['priority'], 'INFO') - payload = msg['payload'] + self.assertEquals(msg.priority, 'INFO') + payload = msg.payload self.assertEquals(payload['tenant_id'], self.project_id) self.assertEquals(payload['user_id'], self.user_id) self.assertEquals(payload['instance_id'], instance.uuid) @@ -4186,7 +4184,7 @@ class ComputeTestCase(BaseTestCase): self.compute.network_api.setup_networks_on_host(c, instance, self.compute.host) - test_notifier.NOTIFICATIONS = [] + fake_notifier.NOTIFICATIONS = [] # start test self.mox.ReplayAll() migrate_data = {'is_shared_storage': False} @@ -4194,12 +4192,12 @@ class ComputeTestCase(BaseTestCase): block_migration=False, migrate_data=migrate_data) self.assertEqual(ret, None) - self.assertEqual(len(test_notifier.NOTIFICATIONS), 2) - msg = test_notifier.NOTIFICATIONS[0] - self.assertEqual(msg['event_type'], + self.assertEqual(len(fake_notifier.NOTIFICATIONS), 2) + msg = fake_notifier.NOTIFICATIONS[0] + self.assertEqual(msg.event_type, 'compute.instance.live_migration.pre.start') - msg = test_notifier.NOTIFICATIONS[1] - self.assertEqual(msg['event_type'], + msg = fake_notifier.NOTIFICATIONS[1] + self.assertEqual(msg.event_type, 'compute.instance.live_migration.pre.end') # cleanup @@ -4218,7 +4216,6 @@ class ComputeTestCase(BaseTestCase): fake_bdms = [dict(volume_id='vol1-id'), dict(volume_id='vol2-id')] # creating mocks - self.mox.StubOutWithMock(rpc, 'call') self.mox.StubOutWithMock(self.compute.driver, 'get_instance_disk_info') self.mox.StubOutWithMock(self.compute.compute_rpcapi, @@ -4430,18 +4427,18 @@ class ComputeTestCase(BaseTestCase): self.compute.network_api.setup_networks_on_host(self.admin_ctxt, mox.IgnoreArg(), self.compute.host) - test_notifier.NOTIFICATIONS = [] + fake_notifier.NOTIFICATIONS = [] self.mox.ReplayAll() self.compute.post_live_migration_at_destination(self.admin_ctxt, self.instance) - self.assertEqual(len(test_notifier.NOTIFICATIONS), 2) - msg = test_notifier.NOTIFICATIONS[0] - self.assertEqual(msg['event_type'], + self.assertEqual(len(fake_notifier.NOTIFICATIONS), 2) + msg = fake_notifier.NOTIFICATIONS[0] + self.assertEqual(msg.event_type, 'compute.instance.live_migration.post.dest.start') - msg = test_notifier.NOTIFICATIONS[1] - self.assertEqual(msg['event_type'], + msg = fake_notifier.NOTIFICATIONS[1] + self.assertEqual(msg.event_type, 'compute.instance.live_migration.post.dest.end') return self.compute.conductor_api.instance_get_by_uuid(self.admin_ctxt, @@ -4477,7 +4474,7 @@ class ComputeTestCase(BaseTestCase): inst_id = instance_ref['id'] instance = jsonutils.to_primitive(db.instance_get(c, inst_id)) - test_notifier.NOTIFICATIONS = [] + fake_notifier.NOTIFICATIONS = [] self.mox.StubOutWithMock(self.compute.network_api, 'setup_networks_on_host') @@ -4490,12 +4487,12 @@ class ComputeTestCase(BaseTestCase): ret = self.compute.rollback_live_migration_at_destination(c, instance=instance) self.assertEqual(ret, None) - self.assertEqual(len(test_notifier.NOTIFICATIONS), 2) - msg = test_notifier.NOTIFICATIONS[0] - self.assertEqual(msg['event_type'], + self.assertEqual(len(fake_notifier.NOTIFICATIONS), 2) + msg = fake_notifier.NOTIFICATIONS[0] + self.assertEqual(msg.event_type, 'compute.instance.live_migration.rollback.dest.start') - msg = test_notifier.NOTIFICATIONS[1] - self.assertEqual(msg['event_type'], + msg = fake_notifier.NOTIFICATIONS[1] + self.assertEqual(msg.event_type, 'compute.instance.live_migration.rollback.dest.end') # cleanup @@ -6547,9 +6544,9 @@ class ComputeAPITestCase(BaseTestCase): self.assertEqual(metadata, {'key1': 'value1', 'key2': 'value2'}) self.assertEqual(meta_changes, [{'key2': ['+', 'value2']}]) - self.assertEquals(len(test_notifier.NOTIFICATIONS), 1) - msg = test_notifier.NOTIFICATIONS[0] - payload = msg['payload'] + self.assertEquals(len(fake_notifier.NOTIFICATIONS), 1) + msg = fake_notifier.NOTIFICATIONS[0] + payload = msg.payload self.assertTrue('metadata' in payload) self.assertEquals(payload['metadata'], metadata) @@ -6564,9 +6561,9 @@ class ComputeAPITestCase(BaseTestCase): 'key3': ['+', 'value3'], }]) - self.assertEquals(len(test_notifier.NOTIFICATIONS), 2) - msg = test_notifier.NOTIFICATIONS[1] - payload = msg['payload'] + self.assertEquals(len(fake_notifier.NOTIFICATIONS), 2) + msg = fake_notifier.NOTIFICATIONS[1] + payload = msg.payload self.assertTrue('metadata' in payload) self.assertEquals(payload['metadata'], metadata) @@ -6575,9 +6572,9 @@ class ComputeAPITestCase(BaseTestCase): self.assertEqual(metadata, {'key3': 'value3'}) self.assertEqual(meta_changes, [{'key2': ['-']}]) - self.assertEquals(len(test_notifier.NOTIFICATIONS), 3) - msg = test_notifier.NOTIFICATIONS[2] - payload = msg['payload'] + self.assertEquals(len(fake_notifier.NOTIFICATIONS), 3) + msg = fake_notifier.NOTIFICATIONS[2] + payload = msg.payload self.assertTrue('metadata' in payload) self.assertEquals(payload['metadata'], {}) @@ -7859,16 +7856,16 @@ class ComputeAPIAggrTestCase(BaseTestCase): # Ensure metadata can be updated. aggr = self.api.create_aggregate(self.context, 'fake_aggregate', 'fake_zone') - test_notifier.NOTIFICATIONS = [] + fake_notifier.NOTIFICATIONS = [] aggr = self.api.update_aggregate(self.context, aggr['id'], {'name': 'new_fake_aggregate'}) self.assertEqual(availability_zones._get_cache().get('cache'), None) - self.assertEqual(len(test_notifier.NOTIFICATIONS), 2) - msg = test_notifier.NOTIFICATIONS[0] - self.assertEqual(msg['event_type'], + self.assertEqual(len(fake_notifier.NOTIFICATIONS), 2) + msg = fake_notifier.NOTIFICATIONS[0] + self.assertEqual(msg.event_type, 'aggregate.updateprop.start') - msg = test_notifier.NOTIFICATIONS[1] - self.assertEqual(msg['event_type'], + msg = fake_notifier.NOTIFICATIONS[1] + self.assertEqual(msg.event_type, 'aggregate.updateprop.end') def test_update_aggregate_metadata(self): @@ -7877,15 +7874,15 @@ class ComputeAPIAggrTestCase(BaseTestCase): 'fake_zone') metadata = {'foo_key1': 'foo_value1', 'foo_key2': 'foo_value2', } - test_notifier.NOTIFICATIONS = [] + fake_notifier.NOTIFICATIONS = [] aggr = self.api.update_aggregate_metadata(self.context, aggr['id'], metadata) - self.assertEqual(len(test_notifier.NOTIFICATIONS), 2) - msg = test_notifier.NOTIFICATIONS[0] - self.assertEqual(msg['event_type'], + self.assertEqual(len(fake_notifier.NOTIFICATIONS), 2) + msg = fake_notifier.NOTIFICATIONS[0] + self.assertEqual(msg.event_type, 'aggregate.updatemetadata.start') - msg = test_notifier.NOTIFICATIONS[1] - self.assertEqual(msg['event_type'], + msg = fake_notifier.NOTIFICATIONS[1] + self.assertEqual(msg.event_type, 'aggregate.updatemetadata.end') metadata['foo_key1'] = None expected = self.api.update_aggregate_metadata(self.context, @@ -7896,24 +7893,24 @@ class ComputeAPIAggrTestCase(BaseTestCase): def test_delete_aggregate(self): # Ensure we can delete an aggregate. - test_notifier.NOTIFICATIONS = [] + fake_notifier.NOTIFICATIONS = [] aggr = self.api.create_aggregate(self.context, 'fake_aggregate', 'fake_zone') - self.assertEqual(len(test_notifier.NOTIFICATIONS), 2) - msg = test_notifier.NOTIFICATIONS[0] - self.assertEqual(msg['event_type'], + self.assertEqual(len(fake_notifier.NOTIFICATIONS), 2) + msg = fake_notifier.NOTIFICATIONS[0] + self.assertEqual(msg.event_type, 'aggregate.create.start') - msg = test_notifier.NOTIFICATIONS[1] - self.assertEqual(msg['event_type'], + msg = fake_notifier.NOTIFICATIONS[1] + self.assertEqual(msg.event_type, 'aggregate.create.end') - test_notifier.NOTIFICATIONS = [] + fake_notifier.NOTIFICATIONS = [] self.api.delete_aggregate(self.context, aggr['id']) - self.assertEqual(len(test_notifier.NOTIFICATIONS), 2) - msg = test_notifier.NOTIFICATIONS[0] - self.assertEqual(msg['event_type'], + self.assertEqual(len(fake_notifier.NOTIFICATIONS), 2) + msg = fake_notifier.NOTIFICATIONS[0] + self.assertEqual(msg.event_type, 'aggregate.delete.start') - msg = test_notifier.NOTIFICATIONS[1] - self.assertEqual(msg['event_type'], + msg = fake_notifier.NOTIFICATIONS[1] + self.assertEqual(msg.event_type, 'aggregate.delete.end') db.aggregate_get(self.context.elevated(read_deleted='yes'), aggr['id']) @@ -7945,15 +7942,15 @@ class ComputeAPIAggrTestCase(BaseTestCase): self.stubs.Set(self.api.compute_rpcapi, 'add_aggregate_host', fake_add_aggregate_host) - test_notifier.NOTIFICATIONS = [] + fake_notifier.NOTIFICATIONS = [] aggr = self.api.add_host_to_aggregate(self.context, aggr['id'], fake_host) - self.assertEqual(len(test_notifier.NOTIFICATIONS), 2) - msg = test_notifier.NOTIFICATIONS[0] - self.assertEqual(msg['event_type'], + self.assertEqual(len(fake_notifier.NOTIFICATIONS), 2) + msg = fake_notifier.NOTIFICATIONS[0] + self.assertEqual(msg.event_type, 'aggregate.addhost.start') - msg = test_notifier.NOTIFICATIONS[1] - self.assertEqual(msg['event_type'], + msg = fake_notifier.NOTIFICATIONS[1] + self.assertEqual(msg.event_type, 'aggregate.addhost.end') self.assertEqual(len(aggr['hosts']), 1) @@ -8047,16 +8044,16 @@ class ComputeAPIAggrTestCase(BaseTestCase): self.stubs.Set(self.api.compute_rpcapi, 'remove_aggregate_host', fake_remove_aggregate_host) - test_notifier.NOTIFICATIONS = [] + fake_notifier.NOTIFICATIONS = [] expected = self.api.remove_host_from_aggregate(self.context, aggr['id'], host_to_remove) - self.assertEqual(len(test_notifier.NOTIFICATIONS), 2) - msg = test_notifier.NOTIFICATIONS[0] - self.assertEqual(msg['event_type'], + self.assertEqual(len(fake_notifier.NOTIFICATIONS), 2) + msg = fake_notifier.NOTIFICATIONS[0] + self.assertEqual(msg.event_type, 'aggregate.removehost.start') - msg = test_notifier.NOTIFICATIONS[1] - self.assertEqual(msg['event_type'], + msg = fake_notifier.NOTIFICATIONS[1] + self.assertEqual(msg.event_type, 'aggregate.removehost.end') self.assertEqual(len(aggr['hosts']) - 1, len(expected['hosts'])) diff --git a/nova/tests/compute/test_compute_api.py b/nova/tests/compute/test_compute_api.py index 980af30cc7..cd6c95faaa 100644 --- a/nova/tests/compute/test_compute_api.py +++ b/nova/tests/compute/test_compute_api.py @@ -422,7 +422,8 @@ class _ComputeAPIUnitTestMixIn(object): if inst.host == 'down-host': inst.info_cache.delete() - compute_utils.notify_about_instance_usage(self.context, + compute_utils.notify_about_instance_usage(mox.IgnoreArg(), + self.context, inst, '%s.start' % delete_type) if not self.is_cells: @@ -445,6 +446,7 @@ class _ComputeAPIUnitTestMixIn(object): reservations=None) db.instance_destroy(self.context, inst.uuid, constraint=None) compute_utils.notify_about_instance_usage( + mox.IgnoreArg(), self.context, inst, '%s.end' % delete_type, system_metadata='sys-meta') diff --git a/nova/tests/compute/test_compute_utils.py b/nova/tests/compute/test_compute_utils.py index e04726e918..accc9dd7f8 100644 --- a/nova/tests/compute/test_compute_utils.py +++ b/nova/tests/compute/test_compute_utils.py @@ -2,6 +2,7 @@ # Copyright 2011 OpenStack Foundation # All Rights Reserved. +# Copyright 2013 Red Hat, Inc. # # 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 @@ -28,13 +29,13 @@ from nova import db from nova import exception from nova.image import glance from nova.network import api as network_api +from nova import notifier as notify from nova.openstack.common import importutils from nova.openstack.common import jsonutils -from nova.openstack.common.notifier import api as notifier_api -from nova.openstack.common.notifier import test_notifier from nova import test from nova.tests import fake_instance_actions from nova.tests import fake_network +from nova.tests import fake_notifier import nova.tests.image.fake CONF = cfg.CONF @@ -236,17 +237,16 @@ class UsageInfoTestCase(test.TestCase): self.stubs.Set(network_api.API, 'get_instance_nw_info', fake_get_nw_info) - notifier_api._reset_drivers() - self.addCleanup(notifier_api._reset_drivers) + fake_notifier.stub_notifier(self.stubs) + self.addCleanup(fake_notifier.reset) + self.flags(use_local=True, group='conductor') self.flags(compute_driver='nova.virt.fake.FakeDriver', - notification_driver=[test_notifier.__name__], network_manager='nova.network.manager.FlatManager') self.compute = importutils.import_object(CONF.compute_manager) self.user_id = 'fake' self.project_id = 'fake' self.context = context.RequestContext(self.user_id, self.project_id) - test_notifier.NOTIFICATIONS = [] def fake_show(meh, context, id): return {'id': 1, 'properties': {'kernel_id': 1, 'ramdisk_id': 1}} @@ -284,12 +284,13 @@ class UsageInfoTestCase(test.TestCase): db.instance_system_metadata_update(self.context, instance['uuid'], sys_metadata, False) instance = db.instance_get(self.context, instance_id) - compute_utils.notify_usage_exists(self.context, instance) - self.assertEquals(len(test_notifier.NOTIFICATIONS), 1) - msg = test_notifier.NOTIFICATIONS[0] - self.assertEquals(msg['priority'], 'INFO') - self.assertEquals(msg['event_type'], 'compute.instance.exists') - payload = msg['payload'] + compute_utils.notify_usage_exists( + notify.get_notifier('compute'), self.context, instance) + self.assertEquals(len(fake_notifier.NOTIFICATIONS), 1) + msg = fake_notifier.NOTIFICATIONS[0] + self.assertEquals(msg.priority, 'INFO') + self.assertEquals(msg.event_type, 'compute.instance.exists') + payload = msg.payload self.assertEquals(payload['tenant_id'], self.project_id) self.assertEquals(payload['user_id'], self.user_id) self.assertEquals(payload['instance_id'], instance['uuid']) @@ -323,11 +324,12 @@ class UsageInfoTestCase(test.TestCase): jsonutils.to_primitive(instance)) instance = db.instance_get(self.context.elevated(read_deleted='yes'), instance_id) - compute_utils.notify_usage_exists(self.context, instance) - msg = test_notifier.NOTIFICATIONS[-1] - self.assertEquals(msg['priority'], 'INFO') - self.assertEquals(msg['event_type'], 'compute.instance.exists') - payload = msg['payload'] + compute_utils.notify_usage_exists( + notify.get_notifier('compute'), self.context, instance) + msg = fake_notifier.NOTIFICATIONS[-1] + self.assertEquals(msg.priority, 'INFO') + self.assertEquals(msg.event_type, 'compute.instance.exists') + payload = msg.payload self.assertEquals(payload['tenant_id'], self.project_id) self.assertEquals(payload['user_id'], self.user_id) self.assertEquals(payload['instance_id'], instance['uuid']) @@ -351,11 +353,12 @@ class UsageInfoTestCase(test.TestCase): instance = db.instance_get(self.context, instance_id) self.compute.terminate_instance(self.context, jsonutils.to_primitive(instance)) - compute_utils.notify_usage_exists(self.context, instance) - msg = test_notifier.NOTIFICATIONS[-1] - self.assertEquals(msg['priority'], 'INFO') - self.assertEquals(msg['event_type'], 'compute.instance.exists') - payload = msg['payload'] + compute_utils.notify_usage_exists( + notify.get_notifier('compute'), self.context, instance) + msg = fake_notifier.NOTIFICATIONS[-1] + self.assertEquals(msg.priority, 'INFO') + self.assertEquals(msg.event_type, 'compute.instance.exists') + payload = msg.payload self.assertEquals(payload['tenant_id'], self.project_id) self.assertEquals(payload['user_id'], self.user_id) self.assertEquals(payload['instance_id'], instance['uuid']) @@ -385,13 +388,15 @@ class UsageInfoTestCase(test.TestCase): # NOTE(russellb) Make sure our instance has the latest system_metadata # in it. instance = db.instance_get(self.context, instance_id) - compute_utils.notify_about_instance_usage(self.context, instance, - 'create.start', extra_usage_info=extra_usage_info) - self.assertEquals(len(test_notifier.NOTIFICATIONS), 1) - msg = test_notifier.NOTIFICATIONS[0] - self.assertEquals(msg['priority'], 'INFO') - self.assertEquals(msg['event_type'], 'compute.instance.create.start') - payload = msg['payload'] + compute_utils.notify_about_instance_usage( + notify.get_notifier('compute'), + self.context, instance, 'create.start', + extra_usage_info=extra_usage_info) + self.assertEquals(len(fake_notifier.NOTIFICATIONS), 1) + msg = fake_notifier.NOTIFICATIONS[0] + self.assertEquals(msg.priority, 'INFO') + self.assertEquals(msg.event_type, 'compute.instance.create.start') + payload = msg.payload self.assertEquals(payload['tenant_id'], self.project_id) self.assertEquals(payload['user_id'], self.user_id) self.assertEquals(payload['instance_id'], instance['uuid']) @@ -416,11 +421,11 @@ class UsageInfoTestCase(test.TestCase): compute_utils.notify_about_aggregate_update(self.context, "create.end", aggregate_payload) - self.assertEquals(len(test_notifier.NOTIFICATIONS), 1) - msg = test_notifier.NOTIFICATIONS[0] - self.assertEquals(msg['priority'], 'INFO') - self.assertEquals(msg['event_type'], 'aggregate.create.end') - payload = msg['payload'] + self.assertEquals(len(fake_notifier.NOTIFICATIONS), 1) + msg = fake_notifier.NOTIFICATIONS[0] + self.assertEquals(msg.priority, 'INFO') + self.assertEquals(msg.event_type, 'aggregate.create.end') + payload = msg.payload self.assertEquals(payload['aggregate_id'], 1) def test_notify_about_aggregate_update_with_name(self): @@ -429,11 +434,11 @@ class UsageInfoTestCase(test.TestCase): compute_utils.notify_about_aggregate_update(self.context, "create.start", aggregate_payload) - self.assertEquals(len(test_notifier.NOTIFICATIONS), 1) - msg = test_notifier.NOTIFICATIONS[0] - self.assertEquals(msg['priority'], 'INFO') - self.assertEquals(msg['event_type'], 'aggregate.create.start') - payload = msg['payload'] + self.assertEquals(len(fake_notifier.NOTIFICATIONS), 1) + msg = fake_notifier.NOTIFICATIONS[0] + self.assertEquals(msg.priority, 'INFO') + self.assertEquals(msg.event_type, 'aggregate.create.start') + payload = msg.payload self.assertEquals(payload['name'], 'fakegroup') def test_notify_about_aggregate_update_without_name_id(self): @@ -442,4 +447,4 @@ class UsageInfoTestCase(test.TestCase): compute_utils.notify_about_aggregate_update(self.context, "create.start", aggregate_payload) - self.assertEquals(len(test_notifier.NOTIFICATIONS), 0) + self.assertEquals(len(fake_notifier.NOTIFICATIONS), 0) diff --git a/nova/tests/conductor/test_conductor.py b/nova/tests/conductor/test_conductor.py index fc1ca4a767..c6ff891600 100644 --- a/nova/tests/conductor/test_conductor.py +++ b/nova/tests/conductor/test_conductor.py @@ -1,4 +1,5 @@ # Copyright 2012 IBM Corp. +# Copyright 2013 Red Hat, Inc. # # 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 @@ -34,8 +35,6 @@ from nova import notifications from nova.objects import instance as instance_obj from nova.objects import migration as migration_obj from nova.openstack.common import jsonutils -from nova.openstack.common.notifier import api as notifier_api -from nova.openstack.common.notifier import test_notifier from nova.openstack.common.rpc import common as rpc_common from nova.openstack.common import timeutils from nova import quota @@ -44,6 +43,7 @@ from nova import test from nova.tests.compute import test_compute from nova.tests import fake_instance from nova.tests import fake_instance_actions +from nova.tests import fake_notifier from nova.tests.objects import test_migration from nova import utils @@ -67,10 +67,8 @@ class _BaseTestCase(object): self.project_id = 'fake' self.context = FakeContext(self.user_id, self.project_id) - notifier_api._reset_drivers() - self.addCleanup(notifier_api._reset_drivers) - self.flags(notification_driver=[test_notifier.__name__]) - test_notifier.NOTIFICATIONS = [] + fake_notifier.stub_notifier(self.stubs) + self.addCleanup(fake_notifier.reset) def _create_fake_instance(self, params=None, type_name='m1.tiny'): if not params: @@ -352,7 +350,6 @@ class _BaseTestCase(object): def test_vol_usage_update(self): self.mox.StubOutWithMock(db, 'vol_usage_update') - self.mox.StubOutWithMock(test_notifier, 'notify') self.mox.StubOutWithMock(compute_utils, 'usage_volume_info') fake_inst = {'uuid': 'fake-uuid', @@ -368,10 +365,6 @@ class _BaseTestCase(object): fake_inst['availability_zone'], False).AndReturn('fake-usage') compute_utils.usage_volume_info('fake-usage').AndReturn('fake-info') - notifier_api.notify(self.context, - 'conductor.%s' % self.conductor_manager.host, - 'volume.usage', notifier_api.INFO, - 'fake-info') self.mox.ReplayAll() @@ -379,6 +372,14 @@ class _BaseTestCase(object): 22, 33, 44, 55, fake_inst, 'fake-update-time', False) + self.assertEqual(1, len(fake_notifier.NOTIFICATIONS)) + msg = fake_notifier.NOTIFICATIONS[0] + self.assertEqual('conductor.%s' % self.conductor_manager.host, + msg.publisher_id) + self.assertEqual('volume.usage', msg.event_type) + self.assertEqual('INFO', msg.priority) + self.assertEqual('fake-info', msg.payload) + def test_compute_node_create(self): self.mox.StubOutWithMock(db, 'compute_node_create') db.compute_node_create(self.context, 'fake-values').AndReturn( @@ -471,7 +472,9 @@ class _BaseTestCase(object): notifications.audit_period_bounds(False).AndReturn(('start', 'end')) notifications.bandwidth_usage(instance, 'start', True).AndReturn( 'bw_usage') - compute_utils.notify_about_instance_usage(self.context, instance, + notifier = self.conductor_manager.notifier + compute_utils.notify_about_instance_usage(notifier, + self.context, instance, 'exists', system_metadata={}, extra_usage_info=info) diff --git a/nova/tests/fake_notifier.py b/nova/tests/fake_notifier.py new file mode 100644 index 0000000000..1352408279 --- /dev/null +++ b/nova/tests/fake_notifier.py @@ -0,0 +1,53 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2013 Red Hat, Inc. +# +# 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 collections +import functools + +from nova import notifier + +NOTIFICATIONS = [] + + +def reset(): + del NOTIFICATIONS[:] + + +FakeMessage = collections.namedtuple('Message', + ['publisher_id', 'priority', + 'event_type', 'payload']) + + +class FakeNotifier(object): + + def __init__(self, publisher_id): + self.publisher_id = publisher_id + for priority in ['debug', 'info', 'warn', 'error', 'critical']: + setattr(self, priority, + functools.partial(self._notify, priority.upper())) + + def prepare(self, publisher_id=None): + if publisher_id is None: + publisher_id = self.publisher_id + return self.__class__(publisher_id) + + def _notify(self, priority, ctxt, event_type, payload): + msg = FakeMessage(self.publisher_id, priority, event_type, payload) + NOTIFICATIONS.append(msg) + + +def stub_notifier(stubs): + stubs.Set(notifier, 'Notifier', FakeNotifier) diff --git a/nova/tests/scheduler/test_scheduler.py b/nova/tests/scheduler/test_scheduler.py index 39f18cd744..4502d4ce86 100644 --- a/nova/tests/scheduler/test_scheduler.py +++ b/nova/tests/scheduler/test_scheduler.py @@ -20,6 +20,7 @@ Tests For Scheduler """ import mox +from oslo.config import cfg from nova.compute import api as compute_api from nova.compute import task_states @@ -31,8 +32,8 @@ from nova import context from nova import db from nova import exception from nova.image import glance +from nova import notifier as notify from nova.objects import instance as instance_obj -from nova.openstack.common.notifier import api as notifier from nova.openstack.common.rpc import common as rpc_common from nova.scheduler import driver from nova.scheduler import manager @@ -45,6 +46,8 @@ from nova.tests import matchers from nova.tests.scheduler import fakes from nova import utils +CONF = cfg.CONF + class SchedulerManagerTestCase(test.NoDBTestCase): """Test case for scheduler manager.""" @@ -433,13 +436,15 @@ class SchedulerManagerTestCase(test.NoDBTestCase): self.mox.StubOutWithMock(db, 'instance_update_and_get_original') self.mox.StubOutWithMock(db, 'instance_fault_create') - self.mox.StubOutWithMock(notifier, 'notify') + self.mox.StubOutWithMock(notify, 'get_notifier') + notifier = self.mox.CreateMockAnything() + notify.get_notifier('conductor', CONF.host).AndReturn(notifier) + notify.get_notifier('scheduler').AndReturn(notifier) db.instance_update_and_get_original(self.context, 'fake-uuid', updates).AndReturn((None, fake_inst)) db.instance_fault_create(self.context, mox.IgnoreArg()) - notifier.notify(self.context, mox.IgnoreArg(), 'scheduler.foo', - notifier.ERROR, mox.IgnoreArg()) + notifier.error(self.context, 'scheduler.foo', mox.IgnoreArg()) self.mox.ReplayAll() self.manager._set_vm_state_and_notify('foo', {'vm_state': 'foo'}, @@ -557,14 +562,15 @@ class SchedulerTestCase(test.NoDBTestCase): instance = {'uuid': 'fake-uuid'} self.mox.StubOutWithMock(db, 'instance_update_and_get_original') self.mox.StubOutWithMock(db, 'instance_fault_create') - self.mox.StubOutWithMock(notifier, 'notify') db.instance_update_and_get_original(self.context, instance['uuid'], mox.IgnoreArg()).AndReturn( (None, instance)) db.instance_fault_create(self.context, mox.IgnoreArg()) - notifier.notify(self.context, mox.IgnoreArg(), - 'scheduler.run_instance', - notifier.ERROR, mox.IgnoreArg()) + self.mox.StubOutWithMock(notify, 'get_notifier') + notifier = self.mox.CreateMockAnything() + notify.get_notifier('conductor', CONF.host).AndReturn(notifier) + notify.get_notifier('scheduler').AndReturn(notifier) + notifier.error(self.context, 'scheduler.run_instance', mox.IgnoreArg()) self.mox.ReplayAll() driver.handle_schedule_error(self.context, diff --git a/nova/tests/scheduler/test_scheduler_utils.py b/nova/tests/scheduler/test_scheduler_utils.py index 84db590f52..31c5b54c5a 100644 --- a/nova/tests/scheduler/test_scheduler_utils.py +++ b/nova/tests/scheduler/test_scheduler_utils.py @@ -16,15 +16,18 @@ Tests For Scheduler Utils """ import mox +from oslo.config import cfg from nova.compute import utils as compute_utils from nova.conductor import api as conductor_api from nova import db from nova import notifications -from nova.openstack.common.notifier import api as notifier +from nova import notifier as notify from nova.scheduler import utils as scheduler_utils from nova import test +CONF = cfg.CONF + class SchedulerUtilsTestCase(test.NoDBTestCase): """Test case for scheduler utils methods.""" @@ -38,13 +41,16 @@ class SchedulerUtilsTestCase(test.NoDBTestCase): service = 'fake-service' method = 'fake-method' exc_info = 'exc_info' - publisher_id = 'fake-publisher-id' self.mox.StubOutWithMock(compute_utils, 'add_instance_fault_from_exc') self.mox.StubOutWithMock(notifications, 'send_update') self.mox.StubOutWithMock(db, 'instance_update_and_get_original') - self.mox.StubOutWithMock(notifier, 'publisher_id') + + self.mox.StubOutWithMock(notify, 'get_notifier') + notifier = self.mox.CreateMockAnything() + notify.get_notifier('conductor', CONF.host).AndReturn(notifier) + notify.get_notifier(service).AndReturn(notifier) old_ref = 'old_ref' new_ref = 'new_ref' @@ -61,15 +67,13 @@ class SchedulerUtilsTestCase(test.NoDBTestCase): payload = dict(request_spec=request_spec, instance_properties=request_spec.get( - 'instance_properties'), + 'instance_properties', {}), instance_id=uuid, state='fake-vm-state', method=method, reason=exc_info) event_type = '%s.%s' % (service, method) - notifier.publisher_id(service).AndReturn(publisher_id) - notifier.notify(self.context, publisher_id, - event_type, notifier.ERROR, payload) + notifier.error(self.context, event_type, payload) self.mox.ReplayAll() diff --git a/nova/tests/test_exception.py b/nova/tests/test_exception.py index 9b53fab980..0b171641e2 100644 --- a/nova/tests/test_exception.py +++ b/nova/tests/test_exception.py @@ -22,21 +22,17 @@ from nova import test class FakeNotifier(object): - """Acts like the nova.notifier.api module.""" - ERROR = 88 + """Acts like messaging.Notifier.""" def __init__(self): - self.provided_publisher = None + self.provided_context = None self.provided_event = None - self.provided_priority = None self.provided_payload = None - def notify(self, context, publisher, event, priority, payload): - self.provided_publisher = publisher + def error(self, context, event, payload): + self.provided_context = context self.provided_event = event - self.provided_priority = priority self.provided_payload = payload - self.provided_context = context def good_function(self, context): @@ -49,18 +45,16 @@ def bad_function_exception(self, context, extra, blah="a", boo="b", zoo=None): class WrapExceptionTestCase(test.TestCase): def test_wrap_exception_good_return(self): - wrapped = exception.wrap_exception('foo', 'bar') + wrapped = exception.wrap_exception('foo') self.assertEquals(99, wrapped(good_function)(1, 2)) def test_wrap_exception_with_notifier(self): notifier = FakeNotifier() - wrapped = exception.wrap_exception(notifier, "publisher") + wrapped = exception.wrap_exception(notifier) ctxt = context.get_admin_context() self.assertRaises(test.TestingException, wrapped(bad_function_exception), 1, ctxt, 3, zoo=3) - self.assertEquals(notifier.provided_publisher, "publisher") self.assertEquals(notifier.provided_event, "bad_function_exception") - self.assertEquals(notifier.provided_priority, notifier.ERROR) self.assertEquals(notifier.provided_context, ctxt) for key in ['exception', 'args']: self.assertTrue(key in notifier.provided_payload.keys()) diff --git a/nova/tests/test_notifications.py b/nova/tests/test_notifications.py index 2ab94e586d..f80b45b100 100644 --- a/nova/tests/test_notifications.py +++ b/nova/tests/test_notifications.py @@ -28,10 +28,9 @@ from nova import context from nova import db from nova.network import api as network_api from nova import notifications -from nova.openstack.common.notifier import api as notifier_api -from nova.openstack.common.notifier import test_notifier from nova import test from nova.tests import fake_network +from nova.tests import fake_notifier CONF = cfg.CONF CONF.import_opt('compute_driver', 'nova.virt.driver') @@ -53,10 +52,10 @@ class NotificationsTestCase(test.TestCase): fake_get_nw_info) fake_network.set_stub_network_methods(self.stubs) - notifier_api._reset_drivers() - self.addCleanup(notifier_api._reset_drivers) + fake_notifier.stub_notifier(self.stubs) + self.addCleanup(fake_notifier.reset) + self.flags(compute_driver='nova.virt.fake.FakeDriver', - notification_driver=[test_notifier.__name__], network_manager='nova.network.manager.FlatManager', notify_on_state_change="vm_and_task_state", host='testhost') @@ -64,7 +63,6 @@ class NotificationsTestCase(test.TestCase): self.user_id = 'fake' self.project_id = 'fake' self.context = context.RequestContext(self.user_id, self.project_id) - test_notifier.NOTIFICATIONS = [] self.instance = self._wrapped_create() @@ -91,7 +89,7 @@ class NotificationsTestCase(test.TestCase): def test_send_api_fault_disabled(self): self.flags(notify_api_faults=False) notifications.send_api_fault("http://example.com/foo", 500, None) - self.assertEquals(0, len(test_notifier.NOTIFICATIONS)) + self.assertEquals(0, len(fake_notifier.NOTIFICATIONS)) def test_send_api_fault(self): self.flags(notify_api_faults=True) @@ -104,13 +102,13 @@ class NotificationsTestCase(test.TestCase): notifications.send_api_fault("http://example.com/foo", 500, exception) - self.assertEquals(1, len(test_notifier.NOTIFICATIONS)) - n = test_notifier.NOTIFICATIONS[0] - self.assertEquals(n['priority'], 'ERROR') - self.assertEquals(n['event_type'], 'api.fault') - self.assertEquals(n['payload']['url'], 'http://example.com/foo') - self.assertEquals(n['payload']['status'], 500) - self.assertTrue(n['payload']['exception'] is not None) + self.assertEquals(1, len(fake_notifier.NOTIFICATIONS)) + n = fake_notifier.NOTIFICATIONS[0] + self.assertEquals(n.priority, 'ERROR') + self.assertEquals(n.event_type, 'api.fault') + self.assertEquals(n.payload['url'], 'http://example.com/foo') + self.assertEquals(n.payload['status'], 500) + self.assertTrue(n.payload['exception'] is not None) def test_notif_disabled(self): @@ -130,7 +128,7 @@ class NotificationsTestCase(test.TestCase): verify_states=True) notifications.send_update(self.context, old, self.instance) - self.assertEquals(0, len(test_notifier.NOTIFICATIONS)) + self.assertEquals(0, len(fake_notifier.NOTIFICATIONS)) def test_task_notif(self): @@ -150,13 +148,13 @@ class NotificationsTestCase(test.TestCase): old_vm_state, new_vm_state, old_task_state, new_task_state, verify_states=True) - self.assertEquals(0, len(test_notifier.NOTIFICATIONS)) + self.assertEquals(0, len(fake_notifier.NOTIFICATIONS)) # ok now enable task state notifcations and re-try self.flags(notify_on_state_change="vm_and_task_state") notifications.send_update(self.context, old, self.instance) - self.assertEquals(1, len(test_notifier.NOTIFICATIONS)) + self.assertEquals(1, len(fake_notifier.NOTIFICATIONS)) def test_send_no_notif(self): @@ -170,7 +168,7 @@ class NotificationsTestCase(test.TestCase): old_vm_state, new_vm_state, old_task_state, new_task_state, service="compute", host=None, verify_states=True) - self.assertEquals(0, len(test_notifier.NOTIFICATIONS)) + self.assertEquals(0, len(fake_notifier.NOTIFICATIONS)) def test_send_on_vm_change(self): @@ -180,7 +178,7 @@ class NotificationsTestCase(test.TestCase): self.instance['uuid'], params) notifications.send_update(self.context, old_ref, new_ref) - self.assertEquals(1, len(test_notifier.NOTIFICATIONS)) + self.assertEquals(1, len(fake_notifier.NOTIFICATIONS)) def test_send_on_task_change(self): @@ -190,23 +188,23 @@ class NotificationsTestCase(test.TestCase): self.instance['uuid'], params) notifications.send_update(self.context, old_ref, new_ref) - self.assertEquals(1, len(test_notifier.NOTIFICATIONS)) + self.assertEquals(1, len(fake_notifier.NOTIFICATIONS)) def test_no_update_with_states(self): notifications.send_update_with_states(self.context, self.instance, vm_states.BUILDING, vm_states.BUILDING, task_states.SPAWNING, task_states.SPAWNING, verify_states=True) - self.assertEquals(0, len(test_notifier.NOTIFICATIONS)) + self.assertEquals(0, len(fake_notifier.NOTIFICATIONS)) def test_vm_update_with_states(self): notifications.send_update_with_states(self.context, self.instance, vm_states.BUILDING, vm_states.ACTIVE, task_states.SPAWNING, task_states.SPAWNING, verify_states=True) - self.assertEquals(1, len(test_notifier.NOTIFICATIONS)) - notif = test_notifier.NOTIFICATIONS[0] - payload = notif["payload"] + self.assertEquals(1, len(fake_notifier.NOTIFICATIONS)) + notif = fake_notifier.NOTIFICATIONS[0] + payload = notif.payload access_ip_v4 = self.instance["access_ip_v4"] access_ip_v6 = self.instance["access_ip_v6"] display_name = self.instance["display_name"] @@ -229,9 +227,9 @@ class NotificationsTestCase(test.TestCase): notifications.send_update_with_states(self.context, self.instance, vm_states.BUILDING, vm_states.BUILDING, task_states.SPAWNING, None, verify_states=True) - self.assertEquals(1, len(test_notifier.NOTIFICATIONS)) - notif = test_notifier.NOTIFICATIONS[0] - payload = notif["payload"] + self.assertEquals(1, len(fake_notifier.NOTIFICATIONS)) + notif = fake_notifier.NOTIFICATIONS[0] + payload = notif.payload access_ip_v4 = self.instance["access_ip_v4"] access_ip_v6 = self.instance["access_ip_v6"] display_name = self.instance["display_name"] @@ -250,31 +248,31 @@ class NotificationsTestCase(test.TestCase): notifications.send_update_with_states(self.context, self.instance, vm_states.BUILDING, vm_states.BUILDING, task_states.SPAWNING, None) - self.assertEquals(1, len(test_notifier.NOTIFICATIONS)) + self.assertEquals(1, len(fake_notifier.NOTIFICATIONS)) # service name should default to 'compute' - notif = test_notifier.NOTIFICATIONS[0] - self.assertEquals('compute.testhost', notif['publisher_id']) + notif = fake_notifier.NOTIFICATIONS[0] + self.assertEquals('compute.testhost', notif.publisher_id) def test_update_with_service_name(self): notifications.send_update_with_states(self.context, self.instance, vm_states.BUILDING, vm_states.BUILDING, task_states.SPAWNING, None, service="testservice") - self.assertEquals(1, len(test_notifier.NOTIFICATIONS)) + self.assertEquals(1, len(fake_notifier.NOTIFICATIONS)) # service name should default to 'compute' - notif = test_notifier.NOTIFICATIONS[0] - self.assertEquals('testservice.testhost', notif['publisher_id']) + notif = fake_notifier.NOTIFICATIONS[0] + self.assertEquals('testservice.testhost', notif.publisher_id) def test_update_with_host_name(self): notifications.send_update_with_states(self.context, self.instance, vm_states.BUILDING, vm_states.BUILDING, task_states.SPAWNING, None, host="someotherhost") - self.assertEquals(1, len(test_notifier.NOTIFICATIONS)) + self.assertEquals(1, len(fake_notifier.NOTIFICATIONS)) # service name should default to 'compute' - notif = test_notifier.NOTIFICATIONS[0] - self.assertEquals('compute.someotherhost', notif['publisher_id']) + notif = fake_notifier.NOTIFICATIONS[0] + self.assertEquals('compute.someotherhost', notif.publisher_id) def test_payload_has_fixed_ip_labels(self): info = notifications.info_from_instance(self.context, self.instance, @@ -284,9 +282,9 @@ class NotificationsTestCase(test.TestCase): def test_send_access_ip_update(self): notifications.send_update(self.context, self.instance, self.instance) - self.assertEquals(1, len(test_notifier.NOTIFICATIONS)) - notif = test_notifier.NOTIFICATIONS[0] - payload = notif["payload"] + self.assertEquals(1, len(fake_notifier.NOTIFICATIONS)) + notif = fake_notifier.NOTIFICATIONS[0] + payload = notif.payload access_ip_v4 = self.instance["access_ip_v4"] access_ip_v6 = self.instance["access_ip_v6"] @@ -297,9 +295,9 @@ class NotificationsTestCase(test.TestCase): param = {"display_name": "new_display_name"} new_name_inst = self._wrapped_create(params=param) notifications.send_update(self.context, self.instance, new_name_inst) - self.assertEquals(1, len(test_notifier.NOTIFICATIONS)) - notif = test_notifier.NOTIFICATIONS[0] - payload = notif["payload"] + self.assertEquals(1, len(fake_notifier.NOTIFICATIONS)) + notif = fake_notifier.NOTIFICATIONS[0] + payload = notif.payload old_display_name = self.instance["display_name"] new_display_name = new_name_inst["display_name"] @@ -323,4 +321,4 @@ class NotificationsTestCase(test.TestCase): fail_sending) notifications.send_update(self.context, self.instance, self.instance) - self.assertEquals(0, len(test_notifier.NOTIFICATIONS)) + self.assertEquals(0, len(fake_notifier.NOTIFICATIONS)) diff --git a/nova/utils.py b/nova/utils.py index 4c29eb937d..09d1dc9dc6 100644 --- a/nova/utils.py +++ b/nova/utils.py @@ -52,7 +52,7 @@ from nova.openstack.common import processutils from nova.openstack.common.rpc import common as rpc_common from nova.openstack.common import timeutils -notify_decorator = 'nova.openstack.common.notifier.api.notify_decorator' +notify_decorator = 'nova.notifications.notify_decorator' monkey_patch_opts = [ cfg.BoolOpt('monkey_patch', @@ -719,10 +719,10 @@ def monkey_patch(): using CONF.monkey_patch_modules. The format is "Module path:Decorator function". Example: - 'nova.api.ec2.cloud:nova.openstack.common.notifier.api.notify_decorator' + 'nova.api.ec2.cloud:nova.notifications.notify_decorator' Parameters of the decorator is as follows. - (See nova.openstack.common.notifier.api.notify_decorator) + (See nova.notifications.notify_decorator) name - name of the function function - object of the function diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py index 6af3974823..462b9844e8 100755 --- a/nova/virt/libvirt/driver.py +++ b/nova/virt/libvirt/driver.py @@ -70,6 +70,7 @@ from nova.compute import vm_mode from nova import context as nova_context from nova import exception from nova.image import glance +from nova import notifier from nova.objects import instance as instance_obj from nova.openstack.common import excutils from nova.openstack.common import fileutils @@ -78,7 +79,6 @@ from nova.openstack.common import importutils from nova.openstack.common import jsonutils from nova.openstack.common import log as logging from nova.openstack.common import loopingcall -from nova.openstack.common.notifier import api as notifier from nova.openstack.common import processutils from nova.openstack.common import xmlutils from nova.pci import pci_whitelist @@ -676,12 +676,9 @@ class LibvirtDriver(driver.ComputeDriver): payload = dict(ip=LibvirtDriver.get_host_ip_addr(), method='_connect', reason=ex) - notifier.notify(nova_context.get_admin_context(), - notifier.publisher_id('compute'), - 'compute.libvirt.error', - notifier.ERROR, - payload) - pass + notifier.get_notifier('compute').error( + nova_context.get_admin_context(), + 'compute.libvirt.error', payload) def get_num_instances(self): """Efficient override of base instance_exists method.""" |