Fixes a deadlock issue when both a model change and a notification of
that change is in the queue.

Change-Id: I76554242b45f90c474fc772572820b9cdde16df2
diff --git a/tests/utests/voltha/core/config/test_config.py b/tests/utests/voltha/core/config/test_config.py
index cb846f5..eda0859 100644
--- a/tests/utests/voltha/core/config/test_config.py
+++ b/tests/utests/voltha/core/config/test_config.py
@@ -561,11 +561,7 @@
             data=dumps(MessageToDict(data, True, True))
         )
 
-        # TODO:  Since the event model is commented out in config_node.py then
-        # this line needs to be commented out as well, otherwise unit test
-        # will fail, hence the build
-        # self.event_mock.assert_called_once_with('model-change-events', event)
-        self.assertTrue(True)
+        self.event_mock.assert_called_once_with('model-change-events', event)
 
     def test_remove_event(self):
         data = Adapter(
@@ -581,12 +577,7 @@
             data=dumps(MessageToDict(data, True, True))
         )
 
-        # TODO:  Since the event model is commented out in config_node.py then
-        # this line needs to be commented out as well, otherwise unit test
-        # will fail, hence the build
-        # self.event_mock.assert_called_once_with('model-change-events', event)
-        self.assertTrue(True)
-
+        self.event_mock.assert_called_once_with('model-change-events', event)
 
 class TestTransactionalLogic(DeepTestsBase):
 
diff --git a/voltha/core/config/config_node.py b/voltha/core/config/config_node.py
index f679786..56518bb 100644
--- a/voltha/core/config/config_node.py
+++ b/voltha/core/config/config_node.py
@@ -304,18 +304,13 @@
                         proceed_on_errors=1,
                     )
 
-
-            # TODO:  This fix needs to be investigated/reworked as it causes an
-            # extra item to be queued in the main branch.  This item does
-            # not get consumed, hence preventing any device update on the
-            # main branch
-            # for change_type, data in change_announcements:
-            #     self._root.enqueue_callback(
-            #         self._mk_event_bus().advertise,
-            #         change_type,
-            #         data,
-            #         hash=rev.hash
-            #     )
+            for change_type, data in change_announcements:
+                self._root.enqueue_notification_callback(
+                    self._mk_event_bus().advertise,
+                    change_type,
+                    data,
+                    hash=rev.hash,
+                )
 
     # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ add operation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
diff --git a/voltha/core/config/config_root.py b/voltha/core/config/config_root.py
index 012ce75..4b1006d 100644
--- a/voltha/core/config/config_root.py
+++ b/voltha/core/config/config_root.py
@@ -33,7 +33,8 @@
         '_kv_store',
         '_loading',
         '_rev_cls',
-        '_deferred_callback_queue'
+        '_deferred_callback_queue',
+        '_notification_deferred_callback_queue'
     )
 
     def __init__(self, initial_data, kv_store=None, rev_cls=ConfigRevision):
@@ -45,6 +46,7 @@
             rev_cls = PersistedConfigRevision
         self._rev_cls = rev_cls
         self._deferred_callback_queue = []
+        self._notification_deferred_callback_queue = []
         super(ConfigRoot, self).__init__(self, initial_data, False)
 
     @property
@@ -146,11 +148,37 @@
     def enqueue_callback(self, func, *args, **kw):
         self._deferred_callback_queue.append((func, args, kw))
 
+    def enqueue_notification_callback(self, func, *args, **kw):
+        """
+        A separate queue is required for notification.  Previously, when the
+        notifications were added to the self._deferred_callback_queue there
+        was a deadlock condition where two callbacks were added (one
+        related to the model change and one for the notification related to
+        that model change).  Since the model change requires the
+        self._deferred_callback_queue to be empty then there was a deadlock
+        in that scenario.   The simple approach to avoid this problem is to
+        have separate queues for model and notification.
+        TODO: Investigate whether there is a need for the
+        self._deferred_callback_queue to handle multiple model events at the same time
+        :param func: callback function
+        :param args: args
+        :param kw: key-value args
+        :return: None
+        """
+        self._notification_deferred_callback_queue.append((func, args, kw))
+
     def execute_deferred_callbacks(self):
+        # First process the model-triggered related callbacks
         while self._deferred_callback_queue:
             func, args, kw = self._deferred_callback_queue.pop(0)
             func(*args, **kw)
 
+        # Execute the notification callbacks
+        while self._notification_deferred_callback_queue:
+            func, args, kw = self._notification_deferred_callback_queue.pop(0)
+            func(*args, **kw)
+
+
     # ~~~~~~~~~~~~~~~~ Persistence related ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
     @classmethod