diff --git a/neutron/agent/linux/daemon.py b/neutron/agent/linux/daemon.py index 2825679a3a..3df12d580e 100644 --- a/neutron/agent/linux/daemon.py +++ b/neutron/agent/linux/daemon.py @@ -19,6 +19,7 @@ import atexit import fcntl import os +import signal import sys from neutron.agent.linux import utils @@ -123,11 +124,15 @@ class Daemon(object): # write pidfile atexit.register(self.delete_pid) + signal.signal(signal.SIGTERM, self.handle_sigterm) self.pidfile.write(os.getpid()) def delete_pid(self): os.remove(str(self.pidfile)) + def handle_sigterm(self, signum, frame): + sys.exit(0) + def start(self): """Start the daemon.""" diff --git a/neutron/tests/unit/test_linux_daemon.py b/neutron/tests/unit/test_linux_daemon.py index 2fc27a4aab..c4cf3223ce 100644 --- a/neutron/tests/unit/test_linux_daemon.py +++ b/neutron/tests/unit/test_linux_daemon.py @@ -160,13 +160,16 @@ class TestDaemon(base.BaseTestCase): d = daemon.Daemon('pidfile') with mock.patch.object(d, '_fork') as fork: with mock.patch.object(daemon, 'atexit') as atexit: - with mock.patch.object(daemon, 'sys') as sys: - sys.stdin.fileno.return_value = 0 - sys.stdout.fileno.return_value = 1 - sys.stderr.fileno.return_value = 2 - d.daemonize() - atexit.register.assert_called_once_with(d.delete_pid) + with mock.patch.object(daemon, 'signal') as signal: + signal.SIGTERM = 15 + with mock.patch.object(daemon, 'sys') as sys: + sys.stdin.fileno.return_value = 0 + sys.stdout.fileno.return_value = 1 + sys.stderr.fileno.return_value = 2 + d.daemonize() + signal.signal.assert_called_once_with(15, d.handle_sigterm) + atexit.register.assert_called_once_with(d.delete_pid) fork.assert_has_calls([mock.call(), mock.call()]) self.os.assert_has_calls([ @@ -185,6 +188,12 @@ class TestDaemon(base.BaseTestCase): d.delete_pid() self.os.remove.assert_called_once_with('pidfile') + def test_handle_sigterm(self): + d = daemon.Daemon('pidfile') + with mock.patch.object(daemon, 'sys') as sys: + d.handle_sigterm(15, 1234) + sys.exit.assert_called_once_with(0) + def test_start(self): self.pidfile.return_value.is_running.return_value = False d = daemon.Daemon('pidfile')