From 0c37b803aea5d8322eea5ed2509156ccef5faa9d Mon Sep 17 00:00:00 2001
From: Fabian Fulga <ffulga@cloudbasesolutions.com>
Date: Tue, 22 Oct 2024 16:54:13 +0300
Subject: [PATCH] Add configurable `notification-driver` for oslo messaging in
 Magnum charm

This change introduces a new configuration option `notification-driver` to the Magnum charm, allowing users to specify the desired Oslo messaging notification driver. Previously, the `oslo_messaging_notifications` driver was hard-coded to `messaging`, limiting flexibility.

The new option allows users to choose from the following drivers: `messaging`, `messagingv2`, `routing`, `log`, `test`, and `noop`.

The `notification-driver` setting is applied in `magnum.conf` as follows:

[oslo_messaging_notifications]
driver = {{ options.notification_driver }}

By default, `notification-driver` is set to `messaging`, keeping the existing behavior unchanged unless explicitly configured. This update provides users with the ability to adjust the notification behavior based on their deployment needs.

Closes-Bug: #2085362
Change-Id: Ib99f44bde1bad2a6f1212c363473e67ed1d32a14
---
 src/config.yaml                               | 11 +++++++
 src/lib/charm/openstack/magnum/magnum.py      | 29 +++++++++++++++++
 src/templates/ussuri/magnum.conf              |  4 ++-
 unit_tests/test_lib_charm_openstack_magnum.py | 31 ++++++++++++++++++-
 4 files changed, 73 insertions(+), 2 deletions(-)

diff --git a/src/config.yaml b/src/config.yaml
index 09c8b00..66acac8 100644
--- a/src/config.yaml
+++ b/src/config.yaml
@@ -68,3 +68,14 @@ options:
       to be present in your OpenStack deployment. Choices are:
         * x509keypair
         * barbican
+  notification-driver:
+    type: string
+    default: "messaging"
+    description: |
+      The Oslo messaging notification driver option to be used. Choices are:
+        * messaging
+        * messagingv2
+        * routing
+        * log
+        * test
+        * noop
diff --git a/src/lib/charm/openstack/magnum/magnum.py b/src/lib/charm/openstack/magnum/magnum.py
index 17d80ab..1235b8d 100644
--- a/src/lib/charm/openstack/magnum/magnum.py
+++ b/src/lib/charm/openstack/magnum/magnum.py
@@ -23,6 +23,8 @@ MAGNUM_CONF = os.path.join(MAGNUM_DIR, 'magnum.conf')
 MAGNUM_PASTE_API = os.path.join(MAGNUM_DIR, 'api-paste.ini')
 KEYSTONE_POLICY = os.path.join(MAGNUM_DIR, 'keystone_auth_default_policy.json')
 POLICY = os.path.join(MAGNUM_DIR, 'policy.json')
+VALID_NOTIFICATION_DRIVERS = [
+    'messaging', 'messagingv2', 'routing', 'log', 'test', 'noop']
 
 MAGNUM_SERVICES = [
     'magnum-api',
@@ -49,6 +51,15 @@ def ca_file_path(arg):
     return ''
 
 
+@adapters.config_property
+def oslo_notification_driver(arg):
+    driver = ch_hookenv.config().get(
+        'notification-driver')
+    if driver in VALID_NOTIFICATION_DRIVERS:
+        return driver
+    return ''
+
+
 def db_sync_done():
     return MagnumCharm.singleton.db_sync_done()
 
@@ -167,3 +178,21 @@ class MagnumCharm(charms_openstack.charm.HAOpenStackCharm):
     def local_unit_name(self):
         """Return local unit name as provided by our ConfigurationClass."""
         return self.configuration_class().local_unit_name
+
+    def _validate_notification_driver(self):
+        driver = self.config.get('notification-driver')
+        if driver not in VALID_NOTIFICATION_DRIVERS:
+            raise ValueError(
+                'Notification driver %s is not valid. Valid '
+                'notifications drivers are: %s' % (
+                    driver, ", ".join(VALID_NOTIFICATION_DRIVERS))
+            )
+
+    def custom_assess_status_check(self):
+        try:
+            self._validate_notification_driver()
+        except Exception as err:
+            msg = ('Invalid notification driver: %s' % err)
+            return 'blocked', msg
+
+        return (None, None)
diff --git a/src/templates/ussuri/magnum.conf b/src/templates/ussuri/magnum.conf
index b698c82..2ddb31b 100644
--- a/src/templates/ussuri/magnum.conf
+++ b/src/templates/ussuri/magnum.conf
@@ -69,8 +69,10 @@ lock_path = /var/lock/magnum
 
 [oslo_messaging_kafka]
 
+{%- if options.oslo_notification_driver %}
 [oslo_messaging_notifications]
-driver = messaging
+driver = {{ options.oslo_notification_driver }}
+{%- endif %}
 
 [oslo_messaging_zmq]
 
diff --git a/unit_tests/test_lib_charm_openstack_magnum.py b/unit_tests/test_lib_charm_openstack_magnum.py
index 2d8e6cd..c1ed17a 100644
--- a/unit_tests/test_lib_charm_openstack_magnum.py
+++ b/unit_tests/test_lib_charm_openstack_magnum.py
@@ -15,7 +15,7 @@
 import mock
 
 import charms_openstack.test_utils as test_utils
-
+import charmhelpers.core.hookenv as hookenv
 import charm.openstack.magnum.magnum as magnum
 
 
@@ -25,6 +25,8 @@ class Helper(test_utils.PatchHelper):
         super().setUp()
         self.patch('charmhelpers.core.hookenv.is_subordinate',
                    return_value=False)
+        self.patch('charmhelpers.core.hookenv.config',
+                   return_value={})
         self.patch_release(magnum.MagnumCharm.release)
 
 
@@ -44,6 +46,33 @@ class TestMagnumCharmConfigProperties(Helper):
         ca_file = magnum.ca_file_path(cls)
         self.assertEqual('/certs/magnum.crt', ca_file)
 
+    def test_validate_notification_driver(self):
+        hookenv.config.return_value = {
+            'notification-driver': 'bogus'
+        }
+        target = magnum.MagnumCharm()
+        with self.assertRaises(ValueError):
+            target._validate_notification_driver()
+
+    def test_custom_assess_status_check(self):
+        hookenv.config.return_value = {
+            'notification-driver': 'messaging'
+        }
+        target = magnum.MagnumCharm()
+        self.assertEqual(target.custom_assess_status_check(), (None, None))
+
+    def test_custom_assess_status_check_invalid(self):
+        hookenv.config.return_value = {
+            'notification-driver': 'bogus',
+        }
+        target = magnum.MagnumCharm()
+        expectedStatus = (
+            'blocked',
+            'Invalid notification driver: Notification driver bogus '
+            'is not valid. Valid notifications drivers are: messaging, '
+            'messagingv2, routing, log, test, noop')
+        self.assertEqual(target.custom_assess_status_check(), expectedStatus)
+
 
 class TestMagnumCharm(Helper):