FWIW I really hate importing things in __init__.py because it leads to strange import chains where things get imported when you didn't expect them to. Is there a reason to put this call here instead of for example in notify/api.py? Vish On Apr 22, 2011, at 8:41 AM, Matt Dietz wrote: > Matt Dietz has proposed merging lp:~cerberus/nova/nova_notifications into lp:nova. > > Requested reviews: > Nova Core (nova-core) > > For more details, see: > https://code.launchpad.net/~cerberus/nova/nova_notifications/+merge/58825 > > Implements a basic mechanism for pushing notifications out to interested parties. The rationale for implementing notifications this way is that the responsibility for them shouldn't fall to Nova. As such, we simply will be pushing messages to a queue where another worker entirely can be written to push messages around to subscribers. > -- > https://code.launchpad.net/~cerberus/nova/nova_notifications/+merge/58825 > You are subscribed to branch lp:nova. > === modified file 'nova/flags.py' > --- nova/flags.py 2011-04-21 23:01:38 +0000 > +++ nova/flags.py 2011-04-22 15:41:24 +0000 > @@ -369,6 +369,9 @@ > DEFINE_string('node_availability_zone', 'nova', > 'availability zone of this node') > > +DEFINE_string('notification_driver', > + 'nova.notifier.no_op_notifier.NoopNotifier', > + 'Default driver for sending notifications') > DEFINE_string('zone_name', 'nova', 'name of this zone') > DEFINE_list('zone_capabilities', > ['hypervisor=xenserver;kvm', 'os=linux;windows'], > > === added directory 'nova/notifier' > === added file 'nova/notifier/__init__.py' > --- nova/notifier/__init__.py 1970-01-01 00:00:00 +0000 > +++ nova/notifier/__init__.py 2011-04-22 15:41:24 +0000 > @@ -0,0 +1,24 @@ > +# Copyright 2011 OpenStack LLC. > +# All Rights Reserved. > +# > +# Licensed under the Apache License, Version 2.0 (the "License"); you may > +# not use this file except in compliance with the License. You may obtain > +# a copy of the License at > +# > +# http://www.apache.org/licenses/LICENSE-2.0 > +# > +# Unless required by applicable law or agreed to in writing, software > +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT > +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the > +# License for the specific language governing permissions and limitations > +# under the License. > + > +from nova import flags > +from nova import utils > + > +FLAGS = flags.FLAGS > + > +def notify(event_name, model): > + """Sends a notification using the specified driver""" > + driver = utils.import_class(FLAGS.notification_driver)() > + driver.notify(event_name, model) > > === added file 'nova/notifier/no_op_notifier.py' > --- nova/notifier/no_op_notifier.py 1970-01-01 00:00:00 +0000 > +++ nova/notifier/no_op_notifier.py 2011-04-22 15:41:24 +0000 > @@ -0,0 +1,19 @@ > +# 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. > + > +class NoopNotifier(object): > + def notify(self, event_name, model): > + """Notifies the recipient of the desired event given the model""" > + pass > > === added file 'nova/notifier/rabbit_notifier.py' > --- nova/notifier/rabbit_notifier.py 1970-01-01 00:00:00 +0000 > +++ nova/notifier/rabbit_notifier.py 2011-04-22 15:41:24 +0000 > @@ -0,0 +1,37 @@ > +# 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 json > + > +import nova.context > + > +from nova import flags > +from nova import rpc > + > +FLAGS = flags.FLAGS > + > +flags.DEFINE_string('notification_topic', 'notifications', > + 'RabbitMQ topic used for Nova notifications') > + > +class RabbitNotifier(object): > + """Sends notifications to a specific RabbitMQ server and topic""" > + pass > + > + def notify(self, event_name, model): > + """Sends a notification to the RabbitMQ""" > + context = nova.context.get_admin_context() > + topic = FLAGS.notification_topic > + msg = { 'event_name': event_name, 'model': model.__dict__ } > + rpc.cast(context, topic, json.dumps(msg)) > > === added file 'nova/tests/test_notifier.py' > --- nova/tests/test_notifier.py 1970-01-01 00:00:00 +0000 > +++ nova/tests/test_notifier.py 2011-04-22 15:41:24 +0000 > @@ -0,0 +1,60 @@ > +# Copyright 2011 OpenStack LLC. > +# All Rights Reserved. > +# > +# Licensed under the Apache License, Version 2.0 (the "License"); you may > +# not use this file except in compliance with the License. You may obtain > +# a copy of the License at > +# > +# http://www.apache.org/licenses/LICENSE-2.0 > +# > +# Unless required by applicable law or agreed to in writing, software > +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT > +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the > +# License for the specific language governing permissions and limitations > +# under the License. > + > +import nova > + > +from nova import flags > +from nova import notifier > +from nova.notifier import no_op_notifier > +from nova import test > + > +import stubout > + > +class NotifierTestCase(test.TestCase): > + """Test case for notifications""" > + def setUp(self): > + super(NotifierTestCase, self).setUp() > + self.stubs = stubout.StubOutForTesting() > + > + def tearDown(self): > + self.stubs.UnsetAll() > + super(NotifierTestCase, self).tearDown() > + > + def test_send_notification(self): > + self.notify_called = False > + def mock_notify(cls, *args): > + self.notify_called = True > + > + self.stubs.Set(nova.notifier.no_op_notifier.NoopNotifier, 'notify', > + mock_notify) > + > + class Mock(object): > + pass > + notifier.notify('derp', Mock()) > + self.assertEqual(self.notify_called, True) > + > + def test_send_rabbit_notification(self): > + self.stubs.Set(nova.flags.FLAGS, 'notification_driver', > + 'nova.notifier.rabbit_notifier.RabbitNotifier') > + self.mock_cast = False > + def mock_cast(cls, *args): > + self.mock_cast = True > + > + class Mock(object): > + pass > + self.stubs.Set(nova.rpc, 'cast', mock_cast) > + notifier.notify('derp', Mock()) > + > + self.assertEqual(self.mock_cast, True) >