From 5021e0f5471871680f3a043f677f59a274be38d2 Mon Sep 17 00:00:00 2001 From: Michael Johnson Date: Sun, 1 Jul 2018 12:10:11 -0700 Subject: [PATCH] Enable oslo_config mutable configurations This patch enables oslo_config mutable configuration for the Octavia control plane processes. The configuration will be updated when the parent process receives a HUP signal. This completes the Rocky goal: Enable mutable configuration. Change-Id: Idaf608c6e5fd2fa74a68c3b562be441a20107a50 Story: 2001545 Task: 6391 --- octavia/cmd/health_manager.py | 16 ++++++++++++++++ octavia/cmd/house_keeping.py | 8 ++++++++ octavia/cmd/octavia_worker.py | 2 +- octavia/tests/unit/cmd/test_health_manager.py | 10 ++++++++++ octavia/tests/unit/cmd/test_house_keeping.py | 6 ++++++ ...e-mutable-configuration-1d7f62a133148767.yaml | 6 ++++++ 6 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 releasenotes/notes/enable-mutable-configuration-1d7f62a133148767.yaml diff --git a/octavia/cmd/health_manager.py b/octavia/cmd/health_manager.py index 6606dbadea..1ed7cef7a3 100644 --- a/octavia/cmd/health_manager.py +++ b/octavia/cmd/health_manager.py @@ -13,6 +13,7 @@ # under the License. # +from functools import partial import multiprocessing import os import signal @@ -34,8 +35,13 @@ CONF = cfg.CONF LOG = logging.getLogger(__name__) +def _mutate_config(*args, **kwargs): + CONF.mutate_config_files() + + def hm_listener(exit_event): signal.signal(signal.SIGINT, signal.SIG_IGN) + signal.signal(signal.SIGHUP, _mutate_config) udp_getter = heartbeat_udp.UDPStatusGetter() while not exit_event.is_set(): try: @@ -50,6 +56,7 @@ def hm_listener(exit_event): def hm_health_check(exit_event): hm = health_manager.HealthManager(exit_event) + signal.signal(signal.SIGHUP, _mutate_config) @periodics.periodic(CONF.health_manager.health_check_interval, run_immediately=True) @@ -69,6 +76,13 @@ def hm_health_check(exit_event): health_check.start() +def _handle_mutate_config(listener_proc_pid, check_proc_pid, *args, **kwargs): + LOG.info("Health Manager recieved HUP signal, mutating config.") + _mutate_config() + os.kill(listener_proc_pid, signal.SIGHUP) + os.kill(check_proc_pid, signal.SIGHUP) + + def main(): service.prepare_service(sys.argv) @@ -99,6 +113,8 @@ def main(): hm_listener_proc.join() signal.signal(signal.SIGTERM, process_cleanup) + signal.signal(signal.SIGHUP, partial( + _handle_mutate_config, hm_listener_proc.pid, hm_health_check_proc.pid)) try: for process in processes: diff --git a/octavia/cmd/house_keeping.py b/octavia/cmd/house_keeping.py index 47f046e204..e9a264184e 100644 --- a/octavia/cmd/house_keeping.py +++ b/octavia/cmd/house_keeping.py @@ -14,6 +14,7 @@ # import datetime +import signal import sys import threading import time @@ -78,6 +79,11 @@ def cert_rotation(): cert_rotate_thread_event.wait(interval) +def _mutate_config(*args, **kwargs): + LOG.info("Housekeeping recieved HUP signal, mutating config.") + CONF.mutate_config_files() + + def main(): service.prepare_service(sys.argv) @@ -101,6 +107,8 @@ def main(): cert_rotate_thread.daemon = True cert_rotate_thread.start() + signal.signal(signal.SIGHUP, _mutate_config) + # Try-Exception block should be at the end to gracefully exit threads try: while True: diff --git a/octavia/cmd/octavia_worker.py b/octavia/cmd/octavia_worker.py index 94a976fb2d..70ce26d14a 100644 --- a/octavia/cmd/octavia_worker.py +++ b/octavia/cmd/octavia_worker.py @@ -34,5 +34,5 @@ def main(): sm = cotyledon.ServiceManager() sm.add(consumer.ConsumerService, workers=CONF.controller_worker.workers, args=(CONF,)) - oslo_config_glue.setup(sm, CONF) + oslo_config_glue.setup(sm, CONF, reload_method="mutate") sm.run() diff --git a/octavia/tests/unit/cmd/test_health_manager.py b/octavia/tests/unit/cmd/test_health_manager.py index 8990396eb7..733bcc696a 100644 --- a/octavia/tests/unit/cmd/test_health_manager.py +++ b/octavia/tests/unit/cmd/test_health_manager.py @@ -93,3 +93,13 @@ class TestHealthManagerCMD(base.TestCase): mock_health_proc.join.assert_called_once_with() mock_kill.assert_called_once_with(mock_health_proc.pid, signal.SIGINT) + + @mock.patch('os.kill') + @mock.patch('oslo_config.cfg.CONF.mutate_config_files') + def test_handle_mutate_config(self, mock_mutate, mock_kill): + health_manager._handle_mutate_config(1, 2) + + mock_mutate.assert_called_once() + + calls = [mock.call(1, signal.SIGHUP), mock.call(2, signal.SIGHUP)] + mock_kill.assert_has_calls(calls) diff --git a/octavia/tests/unit/cmd/test_house_keeping.py b/octavia/tests/unit/cmd/test_house_keeping.py index 701c3b56ff..4d5656c4d7 100644 --- a/octavia/tests/unit/cmd/test_house_keeping.py +++ b/octavia/tests/unit/cmd/test_house_keeping.py @@ -188,3 +188,9 @@ class TestHouseKeepingCMD(base.TestCase): spare_amp_thread_mock.join.assert_called_once_with() db_cleanup_thread_mock.join.assert_called_once_with() cert_rotate_thread_mock.join.assert_called_once_with() + + @mock.patch('oslo_config.cfg.CONF.mutate_config_files') + def test_mutate_config(self, mock_mutate): + house_keeping._mutate_config() + + mock_mutate.assert_called_once() diff --git a/releasenotes/notes/enable-mutable-configuration-1d7f62a133148767.yaml b/releasenotes/notes/enable-mutable-configuration-1d7f62a133148767.yaml new file mode 100644 index 0000000000..630955fe17 --- /dev/null +++ b/releasenotes/notes/enable-mutable-configuration-1d7f62a133148767.yaml @@ -0,0 +1,6 @@ +--- +features: + - | + You can now update the running configuration of the Octavia control + plane processes by sending the parent process a "HUP" signal. + Note: The configuration item must support mutation.