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)
>
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. /code.launchpad .net/~cerberus/ nova/nova_ notifications/ +merge/ 58825 /code.launchpad .net/~cerberus/ nova/nova_ notifications/ +merge/ 58825 string( 'node_availabil ity_zone' , 'nova', string( 'notification_ driver' , no_op_notifier. NoopNotifier' , string( 'zone_name' , 'nova', 'name of this zone') list('zone_ capabilities' , xenserver; kvm', 'os=linux; windows' ], __init_ _.py' __init_ _.py 1970-01-01 00:00:00 +0000 __init_ _.py 2011-04-22 15:41:24 +0000 www.apache. org/licenses/ LICENSE- 2.0 class(FLAGS. notification_ driver) () notify( event_name, model) no_op_notifier. py' no_op_notifier. py 1970-01-01 00:00:00 +0000 no_op_notifier. py 2011-04-22 15:41:24 +0000 www.apache. org/licenses/ LICENSE- 2.0 object) : rabbit_ notifier. py' rabbit_ notifier. py 1970-01-01 00:00:00 +0000 rabbit_ notifier. py 2011-04-22 15:41:24 +0000 www.apache. org/licenses/ LICENSE- 2.0 DEFINE_ string( 'notification_ topic', 'notifications', object) : get_admin_ context( ) ion_topic test_notifier. py' test_notifier. py 1970-01-01 00:00:00 +0000 test_notifier. py 2011-04-22 15:41:24 +0000 www.apache. org/licenses/ LICENSE- 2.0 e(test. TestCase) : estCase, self).setUp() StubOutForTesti ng() UnsetAll( ) estCase, self).tearDown() notification( self): Set(nova. notifier. no_op_notifier. NoopNotifier, 'notify', notify( 'derp', Mock()) l(self. notify_ called, True) rabbit_ notification( self): Set(nova. flags.FLAGS, 'notification_ driver' , rabbit_ notifier. RabbitNotifier' ) Set(nova. rpc, 'cast', mock_cast) notify( 'derp', Mock()) l(self. mock_cast, True)
>
> Requested reviews:
> Nova Core (nova-core)
>
> For more details, see:
> https:/
>
> 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:/
> 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_
> 'availability zone of this node')
>
> +DEFINE_
> + 'nova.notifier.
> + 'Default driver for sending notifications')
> DEFINE_
> DEFINE_
> ['hypervisor=
>
> === added directory 'nova/notifier'
> === added file 'nova/notifier/
> --- nova/notifier/
> +++ nova/notifier/
> @@ -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://
> +#
> +# 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_
> + driver.
>
> === added file 'nova/notifier/
> --- nova/notifier/
> +++ nova/notifier/
> @@ -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://
> +#
> +# 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(
> + def notify(self, event_name, model):
> + """Notifies the recipient of the desired event given the model"""
> + pass
>
> === added file 'nova/notifier/
> --- nova/notifier/
> +++ nova/notifier/
> @@ -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://
> +#
> +# 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.
> + 'RabbitMQ topic used for Nova notifications')
> +
> +class RabbitNotifier(
> + """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.
> + topic = FLAGS.notificat
> + msg = { 'event_name': event_name, 'model': model.__dict__ }
> + rpc.cast(context, topic, json.dumps(msg))
>
> === added file 'nova/tests/
> --- nova/tests/
> +++ nova/tests/
> @@ -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://
> +#
> +# 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 NotifierTestCas
> + """Test case for notifications"""
> + def setUp(self):
> + super(NotifierT
> + self.stubs = stubout.
> +
> + def tearDown(self):
> + self.stubs.
> + super(NotifierT
> +
> + def test_send_
> + self.notify_called = False
> + def mock_notify(cls, *args):
> + self.notify_called = True
> +
> + self.stubs.
> + mock_notify)
> +
> + class Mock(object):
> + pass
> + notifier.
> + self.assertEqua
> +
> + def test_send_
> + self.stubs.
> + 'nova.notifier.
> + self.mock_cast = False
> + def mock_cast(cls, *args):
> + self.mock_cast = True
> +
> + class Mock(object):
> + pass
> + self.stubs.
> + notifier.
> +
> + self.assertEqua
>