From cc406e4edcd1ffe3255f6539c0b34b31ca1e3c9c Mon Sep 17 00:00:00 2001
From: Elancheran Subramanian <esubramanian@godaddy.com>
Date: Thu, 23 Feb 2017 13:20:21 -0800
Subject: [PATCH] Retry support for oslo_messaging_notifications driver

When the underlying RPC is configured with rabbit along
with oslo_messaging_notifications, currently the retry is
not supported. There are retry support specific to drivers,
it's better to have the support uniform across the drivers,
by adding configuration retry on the oslo_messaging_notifier.

Closes-bug: 1666364

Change-Id: I8d547ef2a9e8b086f94a1efca17735f3f3cdaac1
---
 oslo_messaging/notify/notifier.py             |  9 ++++-
 oslo_messaging/tests/notify/test_notifier.py  | 33 ++++++++++++++++---
 .../notes/retry-support-07996ef04dda9482.yaml |  8 +++++
 3 files changed, 45 insertions(+), 5 deletions(-)
 create mode 100644 releasenotes/notes/retry-support-07996ef04dda9482.yaml

diff --git a/oslo_messaging/notify/notifier.py b/oslo_messaging/notify/notifier.py
index caf04aba4..8af1142f9 100644
--- a/oslo_messaging/notify/notifier.py
+++ b/oslo_messaging/notify/notifier.py
@@ -54,6 +54,10 @@ _notifier_opts = [
                                       group='DEFAULT')
                 ],
                 help='AMQP topic used for OpenStack notifications.'),
+    cfg.IntOpt('retry', default=-1,
+               help='The maximum number of attempts to re-send a notification '
+                    'message which failed to be delivered due to a '
+                    'recoverable error. 0 - No retry, -1 - indefinite'),
 ]
 
 _LOG = logging.getLogger(__name__)
@@ -243,7 +247,10 @@ class Notifier(object):
 
         self.transport = transport
         self.publisher_id = publisher_id
-        self.retry = retry
+        if retry is not None:
+            self.retry = retry
+        else:
+            self.retry = conf.oslo_messaging_notifications.retry
 
         self._driver_names = ([driver] if driver is not None else
                               conf.oslo_messaging_notifications.driver)
diff --git a/oslo_messaging/tests/notify/test_notifier.py b/oslo_messaging/tests/notify/test_notifier.py
index 7484311f9..c5a573092 100755
--- a/oslo_messaging/tests/notify/test_notifier.py
+++ b/oslo_messaging/tests/notify/test_notifier.py
@@ -212,7 +212,7 @@ class TestMessagingNotifier(test_utils.BaseTestCase):
                 if hasattr(self, 'retry'):
                     send_kwargs['retry'] = self.retry
                 else:
-                    send_kwargs['retry'] = None
+                    send_kwargs['retry'] = -1
                 target = oslo_messaging.Target(topic='%s.%s' % (topic,
                                                                 self.priority))
                 calls.append(mock.call(target,
@@ -271,7 +271,7 @@ class TestSerializer(test_utils.BaseTestCase):
             'timestamp': str(timeutils.utcnow()),
         }
 
-        self.assertEqual([(dict(user='alice'), message, 'INFO', None)],
+        self.assertEqual([(dict(user='alice'), message, 'INFO', -1)],
                          _impl_test.NOTIFICATIONS)
 
         uuid.uuid4.assert_called_once_with()
@@ -373,6 +373,31 @@ class TestLogNotifier(test_utils.BaseTestCase):
         logger.info.assert_called_once_with(mask_str)
 
 
+class TestNotificationConfig(test_utils.BaseTestCase):
+
+    def test_retry_config(self):
+        conf = self.messaging_conf.conf
+        self.config(driver=['messaging'],
+                    group='oslo_messaging_notifications')
+
+        conf.set_override('retry', 3, group='oslo_messaging_notifications')
+        transport = _FakeTransport(conf)
+        notifier = oslo_messaging.Notifier(transport)
+
+        self.assertEqual(3, notifier.retry)
+
+    def test_notifier_retry_config(self):
+        conf = self.messaging_conf.conf
+        self.config(driver=['messaging'],
+                    group='oslo_messaging_notifications')
+
+        conf.set_override('retry', 3, group='oslo_messaging_notifications')
+        transport = _FakeTransport(conf)
+        notifier = oslo_messaging.Notifier(transport, retry=5)
+
+        self.assertEqual(5, notifier.retry)
+
+
 class TestRoutingNotifier(test_utils.BaseTestCase):
     def setUp(self):
         super(TestRoutingNotifier, self).setUp()
@@ -601,9 +626,9 @@ group_1:
                     self.notifier.info({}, 'my_event', {})
                     self.assertFalse(bar_driver.info.called)
                     rpc_driver.notify.assert_called_once_with(
-                        {}, mock.ANY, 'INFO', None)
+                        {}, mock.ANY, 'INFO', -1)
                     rpc2_driver.notify.assert_called_once_with(
-                        {}, mock.ANY, 'INFO', None)
+                        {}, mock.ANY, 'INFO', -1)
 
 
 class TestNoOpNotifier(test_utils.BaseTestCase):
diff --git a/releasenotes/notes/retry-support-07996ef04dda9482.yaml b/releasenotes/notes/retry-support-07996ef04dda9482.yaml
new file mode 100644
index 000000000..2b5fad7b7
--- /dev/null
+++ b/releasenotes/notes/retry-support-07996ef04dda9482.yaml
@@ -0,0 +1,8 @@
+---
+features:
+  - |
+    | Retry support for oslo_messaging_notifications driver
+    | Configuration param 'retry' is added. Default is -1, indefinite
+
+    * *retry* (default=-1)
+