From f11581221a3739c25e5f7b77b96f3dc8d332af5c Mon Sep 17 00:00:00 2001 From: Tim Simpson Date: Tue, 16 Aug 2011 08:55:17 -0500 Subject: Added list_notifier, a driver for the notifer api which calls a list of other drivers. --- nova/notifier/list_notifier.py | 50 ++++++++++++++++++ nova/tests/notifier/__init__.py | 16 ++++++ nova/tests/notifier/test_list_notifier.py | 85 +++++++++++++++++++++++++++++++ 3 files changed, 151 insertions(+) create mode 100644 nova/notifier/list_notifier.py create mode 100644 nova/tests/notifier/__init__.py create mode 100644 nova/tests/notifier/test_list_notifier.py diff --git a/nova/notifier/list_notifier.py b/nova/notifier/list_notifier.py new file mode 100644 index 000000000..d45a31ecb --- /dev/null +++ b/nova/notifier/list_notifier.py @@ -0,0 +1,50 @@ +# 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 log as logging +from nova import utils + +flags.DEFINE_multistring('list_notifier_drivers', + ['nova.notifier.no_op_notifier'], + 'List of drivers to send notifications') + +FLAGS = flags.FLAGS + +LOG = logging.getLogger('nova.notifier.list_notifier') + +drivers = None + +def __get_drivers(): + """Instantiates and returns drivers based on the flag values.""" + global drivers + if not drivers: + drivers = [utils.import_object(notification_driver) + for notification_driver in FLAGS.list_notifier_drivers] + return drivers + +def notify(message): + """Passes notification to mulitple notifiers in a list.""" + for driver in __get_drivers(): + try: + driver.notify(message) + except Exception as e: + LOG.exception(_("Problem '%(e)s' attempting to send to " + "notification driver %(driver)s." % locals())) + +def _reset_drivers(): + """Used by unit tests to reset the drivers.""" + global drivers + drivers = None diff --git a/nova/tests/notifier/__init__.py b/nova/tests/notifier/__init__.py new file mode 100644 index 000000000..bd862c46a --- /dev/null +++ b/nova/tests/notifier/__init__.py @@ -0,0 +1,16 @@ +# 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.tests import * diff --git a/nova/tests/notifier/test_list_notifier.py b/nova/tests/notifier/test_list_notifier.py new file mode 100644 index 000000000..65c2ecd90 --- /dev/null +++ b/nova/tests/notifier/test_list_notifier.py @@ -0,0 +1,85 @@ +# 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 stubout + +import nova +from nova import context +from nova import flags +from nova import log as logging +from nova import rpc +import nova.notifier.api +from nova.notifier.api import notify +from nova.notifier import log_notifier +from nova.notifier import no_op_notifier +from nova.notifier import list_notifier +from nova.notifier import rabbit_notifier +from nova import test + + +class NotifierListTestCase(test.TestCase): + """Test case for notifications""" + def setUp(self): + super(NotifierListTestCase, self).setUp() + list_notifier._reset_drivers() + self.stubs = stubout.StubOutForTesting() + + def tearDown(self): + self.stubs.UnsetAll() + list_notifier._reset_drivers() + super(NotifierListTestCase, self).tearDown() + + def test_send_notifications_successfully(self): + self.flags(notification_driver='nova.notifier.list_notifier', + list_notifier_drivers=['nova.notifier.no_op_notifier', + 'nova.notifier.no_op_notifier']) + self.notify_count = 0 + + def mock_notify(cls, *args): + self.notify_count += 1 + + self.stubs.Set(nova.notifier.no_op_notifier, 'notify', + mock_notify) + + notify('publisher_id', 'event_type', + nova.notifier.api.WARN, dict(a=3)) + self.assertEqual(self.notify_count, 2) + + def test_send_notifications_with_errors(self): + self.exception_count = 0 + def mock_exception(cls, *args): + self.exception_count += 1 + + self.notify_count = 0 + def mock_notify(cls, *args): + self.notify_count += 1 + + def mock_notify2(cls, *args): + raise RuntimeError("Bad notifier.") + + self.flags(notification_driver='nova.notifier.list_notifier', + list_notifier_drivers=['nova.notifier.no_op_notifier', + 'nova.notifier.log_notifier']) + + list_notifier_log = logging.getLogger('nova.notifier.list_notifier') + list_notifier_log.exception + self.stubs.Set(list_notifier_log, "exception", mock_exception) + self.stubs.Set(nova.notifier.no_op_notifier, 'notify', mock_notify) + self.stubs.Set(nova.notifier.log_notifier, 'notify', mock_notify2) + + notify('publisher_id', 'event_type', nova.notifier.api.WARN, dict(a=3)) + + self.assertEqual(self.notify_count, 1) + self.assertEqual(self.exception_count, 1) -- cgit From e36ebf31699546e48d27754ac1e26b3704399ab0 Mon Sep 17 00:00:00 2001 From: Tim Simpson Date: Mon, 22 Aug 2011 14:06:59 -0500 Subject: Added ability to detect import errors in list_notifier if one or more drivers could not be loaded. --- Authors | 1 + nova/notifier/list_notifier.py | 23 +++++++++++--- nova/tests/notifier/test_list_notifier.py | 52 +++++++++++++++---------------- 3 files changed, 46 insertions(+), 30 deletions(-) diff --git a/Authors b/Authors index 02fe46c79..c8193e3f4 100644 --- a/Authors +++ b/Authors @@ -99,6 +99,7 @@ Scott Moser Soren Hansen Stephanie Reese Thierry Carrez +Tim Simpson Todd Willey Trey Morris Tushar Patil diff --git a/nova/notifier/list_notifier.py b/nova/notifier/list_notifier.py index d45a31ecb..78d51628c 100644 --- a/nova/notifier/list_notifier.py +++ b/nova/notifier/list_notifier.py @@ -16,6 +16,7 @@ from nova import flags from nova import log as logging from nova import utils +from nova.exception import ClassNotFound flags.DEFINE_multistring('list_notifier_drivers', ['nova.notifier.no_op_notifier'], @@ -27,17 +28,31 @@ LOG = logging.getLogger('nova.notifier.list_notifier') drivers = None -def __get_drivers(): + +class ImportFailureNotifier(object): + + def __init__(self, exception): + self.exception = exception + + def notify(message): + raise self.exception + + +def _get_drivers(): """Instantiates and returns drivers based on the flag values.""" global drivers if not drivers: - drivers = [utils.import_object(notification_driver) - for notification_driver in FLAGS.list_notifier_drivers] + drivers = [] + for notification_driver in FLAGS.list_notifier_drivers: + try: + drivers.append(utils.import_object(notification_driver)) + except ClassNotFound as e: + drivers.append(ImportFailureNotifier(e)) return drivers def notify(message): """Passes notification to mulitple notifiers in a list.""" - for driver in __get_drivers(): + for driver in _get_drivers(): try: driver.notify(message) except Exception as e: diff --git a/nova/tests/notifier/test_list_notifier.py b/nova/tests/notifier/test_list_notifier.py index 65c2ecd90..ca8b3e0a7 100644 --- a/nova/tests/notifier/test_list_notifier.py +++ b/nova/tests/notifier/test_list_notifier.py @@ -31,10 +31,26 @@ from nova import test class NotifierListTestCase(test.TestCase): """Test case for notifications""" + def setUp(self): super(NotifierListTestCase, self).setUp() list_notifier._reset_drivers() self.stubs = stubout.StubOutForTesting() + # Mock log to add one to exception_count when log.exception is called + def mock_exception(cls, *args): + self.exception_count += 1 + self.exception_count = 0 + list_notifier_log = logging.getLogger('nova.notifier.list_notifier') + self.stubs.Set(list_notifier_log, "exception", mock_exception) + # Mock no_op notifier to add one to notify_count when called. + def mock_notify(cls, *args): + self.notify_count += 1 + self.notify_count = 0 + self.stubs.Set(nova.notifier.no_op_notifier, 'notify', mock_notify) + # Mock log_notifier to raise RuntimeError when called. + def mock_notify2(cls, *args): + raise RuntimeError("Bad notifier.") + self.stubs.Set(nova.notifier.log_notifier, 'notify', mock_notify2) def tearDown(self): self.stubs.UnsetAll() @@ -45,41 +61,25 @@ class NotifierListTestCase(test.TestCase): self.flags(notification_driver='nova.notifier.list_notifier', list_notifier_drivers=['nova.notifier.no_op_notifier', 'nova.notifier.no_op_notifier']) - self.notify_count = 0 - - def mock_notify(cls, *args): - self.notify_count += 1 - - self.stubs.Set(nova.notifier.no_op_notifier, 'notify', - mock_notify) - notify('publisher_id', 'event_type', nova.notifier.api.WARN, dict(a=3)) self.assertEqual(self.notify_count, 2) + self.assertEqual(self.exception_count, 0) def test_send_notifications_with_errors(self): - self.exception_count = 0 - def mock_exception(cls, *args): - self.exception_count += 1 - - self.notify_count = 0 - def mock_notify(cls, *args): - self.notify_count += 1 - - def mock_notify2(cls, *args): - raise RuntimeError("Bad notifier.") self.flags(notification_driver='nova.notifier.list_notifier', list_notifier_drivers=['nova.notifier.no_op_notifier', 'nova.notifier.log_notifier']) - - list_notifier_log = logging.getLogger('nova.notifier.list_notifier') - list_notifier_log.exception - self.stubs.Set(list_notifier_log, "exception", mock_exception) - self.stubs.Set(nova.notifier.no_op_notifier, 'notify', mock_notify) - self.stubs.Set(nova.notifier.log_notifier, 'notify', mock_notify2) - notify('publisher_id', 'event_type', nova.notifier.api.WARN, dict(a=3)) - self.assertEqual(self.notify_count, 1) self.assertEqual(self.exception_count, 1) + + def test_when_driver_fails_to_import(self): + self.flags(notification_driver='nova.notifier.list_notifier', + list_notifier_drivers=['nova.notifier.no_op_notifier', + 'nova.notifier.logo_notifier', + 'fdsjgsdfhjkhgsfkj']) + notify('publisher_id', 'event_type', nova.notifier.api.WARN, dict(a=3)) + self.assertEqual(self.exception_count, 2) + self.assertEqual(self.notify_count, 1) -- cgit From 51344d7be195f9342d24d461f4c07fa1c9141da4 Mon Sep 17 00:00:00 2001 From: Tim Simpson Date: Mon, 22 Aug 2011 15:21:31 -0500 Subject: Changed list_notifier to call sys.exit if a notification driver could not be found. --- nova/notifier/list_notifier.py | 15 ++++----------- nova/tests/notifier/test_list_notifier.py | 15 ++++++++++----- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/nova/notifier/list_notifier.py b/nova/notifier/list_notifier.py index 78d51628c..21067df55 100644 --- a/nova/notifier/list_notifier.py +++ b/nova/notifier/list_notifier.py @@ -13,6 +13,8 @@ # License for the specific language governing permissions and limitations # under the License. +import sys + from nova import flags from nova import log as logging from nova import utils @@ -29,15 +31,6 @@ LOG = logging.getLogger('nova.notifier.list_notifier') drivers = None -class ImportFailureNotifier(object): - - def __init__(self, exception): - self.exception = exception - - def notify(message): - raise self.exception - - def _get_drivers(): """Instantiates and returns drivers based on the flag values.""" global drivers @@ -46,8 +39,8 @@ def _get_drivers(): for notification_driver in FLAGS.list_notifier_drivers: try: drivers.append(utils.import_object(notification_driver)) - except ClassNotFound as e: - drivers.append(ImportFailureNotifier(e)) + except ClassNotFound: + sys.exit(1) return drivers def notify(message): diff --git a/nova/tests/notifier/test_list_notifier.py b/nova/tests/notifier/test_list_notifier.py index ca8b3e0a7..bab1a0ab8 100644 --- a/nova/tests/notifier/test_list_notifier.py +++ b/nova/tests/notifier/test_list_notifier.py @@ -14,18 +14,15 @@ # under the License. import stubout +import sys import nova -from nova import context -from nova import flags from nova import log as logging -from nova import rpc import nova.notifier.api from nova.notifier.api import notify from nova.notifier import log_notifier from nova.notifier import no_op_notifier from nova.notifier import list_notifier -from nova.notifier import rabbit_notifier from nova import test @@ -51,6 +48,11 @@ class NotifierListTestCase(test.TestCase): def mock_notify2(cls, *args): raise RuntimeError("Bad notifier.") self.stubs.Set(nova.notifier.log_notifier, 'notify', mock_notify2) + # mock sys.exit so we don't actually kill the program during our tests. + self.sys_exit_code = 0 + def mock_sys_exit(code): + self.sys_exit_code += code + self.stubs.Set(sys, 'exit', mock_sys_exit) def tearDown(self): self.stubs.UnsetAll() @@ -65,6 +67,7 @@ class NotifierListTestCase(test.TestCase): nova.notifier.api.WARN, dict(a=3)) self.assertEqual(self.notify_count, 2) self.assertEqual(self.exception_count, 0) + self.assertEqual(self.sys_exit_code, 0) def test_send_notifications_with_errors(self): @@ -74,6 +77,7 @@ class NotifierListTestCase(test.TestCase): notify('publisher_id', 'event_type', nova.notifier.api.WARN, dict(a=3)) self.assertEqual(self.notify_count, 1) self.assertEqual(self.exception_count, 1) + self.assertEqual(self.sys_exit_code, 0) def test_when_driver_fails_to_import(self): self.flags(notification_driver='nova.notifier.list_notifier', @@ -81,5 +85,6 @@ class NotifierListTestCase(test.TestCase): 'nova.notifier.logo_notifier', 'fdsjgsdfhjkhgsfkj']) notify('publisher_id', 'event_type', nova.notifier.api.WARN, dict(a=3)) - self.assertEqual(self.exception_count, 2) + self.assertEqual(self.exception_count, 0) self.assertEqual(self.notify_count, 1) + self.assertEqual(self.sys_exit_code, 2) -- cgit From b75f90e0d83e50b6699a8e6efc60cc97a00c0678 Mon Sep 17 00:00:00 2001 From: Tim Simpson Date: Tue, 23 Aug 2011 13:12:54 -0500 Subject: Switched list_notifier to log an exception each time notify is called, for each notification driver that failed to import. --- nova/notifier/list_notifier.py | 13 +++++++++++-- nova/tests/notifier/test_list_notifier.py | 10 +--------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/nova/notifier/list_notifier.py b/nova/notifier/list_notifier.py index 21067df55..aa9c236b0 100644 --- a/nova/notifier/list_notifier.py +++ b/nova/notifier/list_notifier.py @@ -30,6 +30,15 @@ LOG = logging.getLogger('nova.notifier.list_notifier') drivers = None +class ImportFailureNotifier(object): + """Noisily re-raises some exception over-and-over when notify is called.""" + + def __init__(self, exception): + self.exception = exception + + def notify(message): + raise self.exception + def _get_drivers(): """Instantiates and returns drivers based on the flag values.""" @@ -39,8 +48,8 @@ def _get_drivers(): for notification_driver in FLAGS.list_notifier_drivers: try: drivers.append(utils.import_object(notification_driver)) - except ClassNotFound: - sys.exit(1) + except ClassNotFound as e: + drivers.append(ImportFailureNotifier(e)) return drivers def notify(message): diff --git a/nova/tests/notifier/test_list_notifier.py b/nova/tests/notifier/test_list_notifier.py index bab1a0ab8..ad2b039c5 100644 --- a/nova/tests/notifier/test_list_notifier.py +++ b/nova/tests/notifier/test_list_notifier.py @@ -48,11 +48,6 @@ class NotifierListTestCase(test.TestCase): def mock_notify2(cls, *args): raise RuntimeError("Bad notifier.") self.stubs.Set(nova.notifier.log_notifier, 'notify', mock_notify2) - # mock sys.exit so we don't actually kill the program during our tests. - self.sys_exit_code = 0 - def mock_sys_exit(code): - self.sys_exit_code += code - self.stubs.Set(sys, 'exit', mock_sys_exit) def tearDown(self): self.stubs.UnsetAll() @@ -67,7 +62,6 @@ class NotifierListTestCase(test.TestCase): nova.notifier.api.WARN, dict(a=3)) self.assertEqual(self.notify_count, 2) self.assertEqual(self.exception_count, 0) - self.assertEqual(self.sys_exit_code, 0) def test_send_notifications_with_errors(self): @@ -77,7 +71,6 @@ class NotifierListTestCase(test.TestCase): notify('publisher_id', 'event_type', nova.notifier.api.WARN, dict(a=3)) self.assertEqual(self.notify_count, 1) self.assertEqual(self.exception_count, 1) - self.assertEqual(self.sys_exit_code, 0) def test_when_driver_fails_to_import(self): self.flags(notification_driver='nova.notifier.list_notifier', @@ -85,6 +78,5 @@ class NotifierListTestCase(test.TestCase): 'nova.notifier.logo_notifier', 'fdsjgsdfhjkhgsfkj']) notify('publisher_id', 'event_type', nova.notifier.api.WARN, dict(a=3)) - self.assertEqual(self.exception_count, 0) + self.assertEqual(self.exception_count, 2) self.assertEqual(self.notify_count, 1) - self.assertEqual(self.sys_exit_code, 2) -- cgit From cbf8b3b36dde763164fcfd06e1d3c5732f57311d Mon Sep 17 00:00:00 2001 From: Tim Simpson Date: Tue, 23 Aug 2011 15:50:39 -0500 Subject: Fixed some pep8 and pylint issues. --- nova/notifier/list_notifier.py | 7 ++++--- nova/tests/notifier/test_list_notifier.py | 6 ++++++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/nova/notifier/list_notifier.py b/nova/notifier/list_notifier.py index aa9c236b0..955ae1b57 100644 --- a/nova/notifier/list_notifier.py +++ b/nova/notifier/list_notifier.py @@ -13,8 +13,6 @@ # License for the specific language governing permissions and limitations # under the License. -import sys - from nova import flags from nova import log as logging from nova import utils @@ -30,13 +28,14 @@ LOG = logging.getLogger('nova.notifier.list_notifier') drivers = None + class ImportFailureNotifier(object): """Noisily re-raises some exception over-and-over when notify is called.""" def __init__(self, exception): self.exception = exception - def notify(message): + def notify(self, message): raise self.exception @@ -52,6 +51,7 @@ def _get_drivers(): drivers.append(ImportFailureNotifier(e)) return drivers + def notify(message): """Passes notification to mulitple notifiers in a list.""" for driver in _get_drivers(): @@ -61,6 +61,7 @@ def notify(message): LOG.exception(_("Problem '%(e)s' attempting to send to " "notification driver %(driver)s." % locals())) + def _reset_drivers(): """Used by unit tests to reset the drivers.""" global drivers diff --git a/nova/tests/notifier/test_list_notifier.py b/nova/tests/notifier/test_list_notifier.py index ad2b039c5..b77720759 100644 --- a/nova/tests/notifier/test_list_notifier.py +++ b/nova/tests/notifier/test_list_notifier.py @@ -34,19 +34,25 @@ class NotifierListTestCase(test.TestCase): list_notifier._reset_drivers() self.stubs = stubout.StubOutForTesting() # Mock log to add one to exception_count when log.exception is called + def mock_exception(cls, *args): self.exception_count += 1 + self.exception_count = 0 list_notifier_log = logging.getLogger('nova.notifier.list_notifier') self.stubs.Set(list_notifier_log, "exception", mock_exception) # Mock no_op notifier to add one to notify_count when called. + def mock_notify(cls, *args): self.notify_count += 1 + self.notify_count = 0 self.stubs.Set(nova.notifier.no_op_notifier, 'notify', mock_notify) # Mock log_notifier to raise RuntimeError when called. + def mock_notify2(cls, *args): raise RuntimeError("Bad notifier.") + self.stubs.Set(nova.notifier.log_notifier, 'notify', mock_notify2) def tearDown(self): -- cgit From 0fc12640a09792fbf278c050c35c62933afcb68d Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Tue, 23 Aug 2011 15:53:59 -0700 Subject: fix iscsi adm command --- nova/volume/driver.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nova/volume/driver.py b/nova/volume/driver.py index c99534c07..7d2fb45d4 100644 --- a/nova/volume/driver.py +++ b/nova/volume/driver.py @@ -495,7 +495,7 @@ class ISCSIDriver(VolumeDriver): (out, err) = self._execute('iscsiadm', '-m', 'node', '-T', iscsi_properties['target_iqn'], '-p', iscsi_properties['target_portal'], - iscsi_command, run_as_root=True) + *iscsi_command, run_as_root=True) LOG.debug("iscsiadm %s: stdout=%s stderr=%s" % (iscsi_command, out, err)) return (out, err) -- cgit