From dd174fbfde8c2fa173825d495a724865e3bdc87b Mon Sep 17 00:00:00 2001 From: Sebastian Lohff Date: Tue, 14 May 2019 10:55:18 +0200 Subject: [PATCH] Make PID availabe as formatstring in backdoor path When multiple processes are spawned with the same configuration each process has the same backdoor_socket path configured and only the first process able to bind to the socket can later be accessed via the backdoor. To give each process a unique socket path we now expose the PID of the process as a format string argument, which can then be used like this: backdoor_socket = /var/lib/neutron/backdoor-{pid} Change-Id: I3f86f4867eb0cd5010abadf68620aa3450d3e64d --- oslo_service/_options.py | 3 ++- oslo_service/eventlet_backdoor.py | 12 ++++++++-- oslo_service/tests/test_eventlet_backdoor.py | 24 +++++++++++++++++++ ...backdoor-socket-path-1863eaad1dd08556.yaml | 8 +++++++ 4 files changed, 44 insertions(+), 3 deletions(-) create mode 100644 releasenotes/notes/support-pid-in-eventlet-backdoor-socket-path-1863eaad1dd08556.yaml diff --git a/oslo_service/_options.py b/oslo_service/_options.py index f70f5b4a..0b356d21 100644 --- a/oslo_service/_options.py +++ b/oslo_service/_options.py @@ -31,7 +31,8 @@ eventlet_backdoor_opts = [ " option is mutually exclusive with 'backdoor_port' in" " that only one should be provided. If both are provided" " then the existence of this option overrides the usage of" - " that option.") + " that option. Inside the path {pid} will be replaced with" + " the PID of the current process.") ] periodic_opts = [ diff --git a/oslo_service/eventlet_backdoor.py b/oslo_service/eventlet_backdoor.py index 5e3186f3..16daffbf 100644 --- a/oslo_service/eventlet_backdoor.py +++ b/oslo_service/eventlet_backdoor.py @@ -214,8 +214,16 @@ def _initialize_if_enabled(conf): # listen(). In any case, pull the port number out here. where_running = sock.getsockname()[1] else: - sock = _try_open_unix_domain_socket(conf.backdoor_socket) - where_running = conf.backdoor_socket + try: + backdoor_socket_path = conf.backdoor_socket.format(pid=os.getpid()) + except (KeyError, IndexError, ValueError) as e: + backdoor_socket_path = conf.backdoor_socket + LOG.warning("Could not apply format string to eventlet " + "backdoor socket path ({}) - continuing with " + "unformatted path" + "".format(e)) + sock = _try_open_unix_domain_socket(backdoor_socket_path) + where_running = backdoor_socket_path # NOTE(johannes): The standard sys.displayhook will print the value of # the last expression and set it to __builtin__._, which overwrites diff --git a/oslo_service/tests/test_eventlet_backdoor.py b/oslo_service/tests/test_eventlet_backdoor.py index 480761e1..93d81054 100644 --- a/oslo_service/tests/test_eventlet_backdoor.py +++ b/oslo_service/tests/test_eventlet_backdoor.py @@ -38,6 +38,30 @@ class BackdoorSocketPathTest(base.ServiceBaseTestCase): path = eventlet_backdoor.initialize_if_enabled(self.conf) self.assertEqual("/tmp/my_special_socket", path) + @mock.patch.object(eventlet, 'spawn') + @mock.patch.object(eventlet, 'listen') + def test_backdoor_path_with_format_string(self, listen_mock, spawn_mock): + self.config(backdoor_socket="/tmp/my_special_socket-{pid}") + listen_mock.side_effect = mock.Mock() + path = eventlet_backdoor.initialize_if_enabled(self.conf) + expected_path = "/tmp/my_special_socket-{}".format(os.getpid()) + self.assertEqual(expected_path, path) + + @mock.patch.object(eventlet, 'spawn') + @mock.patch.object(eventlet, 'listen') + def test_backdoor_path_with_broken_format_string(self, listen_mock, + spawn_mock): + broken_socket_paths = [ + "/tmp/my_special_socket-{}", + "/tmp/my_special_socket-{broken", + "/tmp/my_special_socket-{broken}", + ] + for socket_path in broken_socket_paths: + self.config(backdoor_socket=socket_path) + listen_mock.side_effect = mock.Mock() + path = eventlet_backdoor.initialize_if_enabled(self.conf) + self.assertEqual(socket_path, path) + @mock.patch.object(os, 'unlink') @mock.patch.object(eventlet, 'spawn') @mock.patch.object(eventlet, 'listen') diff --git a/releasenotes/notes/support-pid-in-eventlet-backdoor-socket-path-1863eaad1dd08556.yaml b/releasenotes/notes/support-pid-in-eventlet-backdoor-socket-path-1863eaad1dd08556.yaml new file mode 100644 index 00000000..1cbd221f --- /dev/null +++ b/releasenotes/notes/support-pid-in-eventlet-backdoor-socket-path-1863eaad1dd08556.yaml @@ -0,0 +1,8 @@ +--- +features: + - | + The config option backdoor_socket_path now is a format string that + supports {pid}, which will be replaced with the PID of the current + process. This makes the eventlet backdoor accessible when spawning + multiple processes with the same backdoor_socket_path inside the + configuration.