self.schedule_resync(e)
LOG.exception(_('Unable to sync network state.'))
+ @utils.exception_logger()
def _periodic_resync_helper(self):
"""Resync the dhcp state at the configured interval."""
while True:
if network:
self.configure_dhcp_for_network(network)
+ @utils.exception_logger()
def safe_configure_dhcp_for_network(self, network):
try:
self.configure_dhcp_for_network(network)
from oslo.config import cfg
from neutron.common import constants as q_const
+from neutron.openstack.common import excutils
from neutron.openstack.common import lockutils
from neutron.openstack.common import log as logging
return multiprocessing.cpu_count()
except NotImplementedError:
return 1
+
+
+class exception_logger(object):
+ """Wrap a function and log raised exception
+
+ :param logger: the logger to log the exception default is LOG.exception
+
+ :returns: origin value if no exception raised; re-raise the exception if
+ any occurred
+
+ """
+ def __init__(self, logger=None):
+ self.logger = logger
+
+ def __call__(self, func):
+ if self.logger is None:
+ LOG = logging.getLogger(func.__module__)
+ self.logger = LOG.exception
+
+ def call(*args, **kwargs):
+ try:
+ return func(*args, **kwargs)
+ except Exception as e:
+ with excutils.save_and_reraise_exception():
+ self.logger(e)
+ return call
# License for the specific language governing permissions and limitations
# under the License.
+import eventlet
import mock
import testtools
expected = ((42, 'baz'), ('aaa', 'zzz'), ('foo', 'bar'))
output_tuple = utils.dict2tuple(input_dict)
self.assertEqual(expected, output_tuple)
+
+
+class TestExceptionLogger(base.BaseTestCase):
+ def test_normal_call(self):
+ result = "Result"
+
+ @utils.exception_logger()
+ def func():
+ return result
+
+ self.assertEqual(result, func())
+
+ def test_raise(self):
+ result = "Result"
+
+ @utils.exception_logger()
+ def func():
+ raise RuntimeError(result)
+
+ self.assertRaises(RuntimeError, func)
+
+ def test_spawn_normal(self):
+ result = "Result"
+ logger = mock.Mock()
+
+ @utils.exception_logger(logger=logger)
+ def func():
+ return result
+
+ gt = eventlet.spawn(func)
+ self.assertEqual(result, gt.wait())
+ self.assertFalse(logger.called)
+
+ def test_spawn_raise(self):
+ result = "Result"
+ logger = mock.Mock()
+
+ @utils.exception_logger(logger=logger)
+ def func():
+ raise RuntimeError(result)
+
+ gt = eventlet.spawn(func)
+ self.assertRaises(RuntimeError, gt.wait)
+ self.assertTrue(logger.called)
+
+ def test_pool_spawn_normal(self):
+ logger = mock.Mock()
+ calls = mock.Mock()
+
+ @utils.exception_logger(logger=logger)
+ def func(i):
+ calls(i)
+
+ pool = eventlet.GreenPool(4)
+ for i in range(0, 4):
+ pool.spawn(func, i)
+ pool.waitall()
+
+ calls.assert_has_calls([mock.call(0), mock.call(1),
+ mock.call(2), mock.call(3)],
+ any_order=True)
+ self.assertFalse(logger.called)
+
+ def test_pool_spawn_raise(self):
+ logger = mock.Mock()
+ calls = mock.Mock()
+
+ @utils.exception_logger(logger=logger)
+ def func(i):
+ if i == 2:
+ raise RuntimeError(2)
+ else:
+ calls(i)
+
+ pool = eventlet.GreenPool(4)
+ for i in range(0, 4):
+ pool.spawn(func, i)
+ pool.waitall()
+
+ calls.assert_has_calls([mock.call(0), mock.call(1), mock.call(3)],
+ any_order=True)
+ self.assertTrue(logger.called)