Ensure "keepalived" is correcly disabled
To stop a "keepalived" process, a SIGTERM signal is sent. This patch checks if the process is not present in the system. If the instance is still running after a short time, a SIGKILL signal is sent. Change-Id: I2e784ea7e00c145135288bf309bb34ce311ac15c Closes-Bug: #1908057
This commit is contained in:
parent
2d4b3aa119
commit
2618acff51
@ -15,6 +15,7 @@
|
|||||||
import errno
|
import errno
|
||||||
import itertools
|
import itertools
|
||||||
import os
|
import os
|
||||||
|
import signal
|
||||||
|
|
||||||
import netaddr
|
import netaddr
|
||||||
from neutron_lib import constants
|
from neutron_lib import constants
|
||||||
@ -41,6 +42,7 @@ HEALTH_CHECK_NAME = 'ha_health_check'
|
|||||||
_IS_NO_TRACK_SUPPORTED = None
|
_IS_NO_TRACK_SUPPORTED = None
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
SIGTERM_TIMEOUT = 5
|
||||||
|
|
||||||
|
|
||||||
def _is_keepalived_use_no_track_supported():
|
def _is_keepalived_use_no_track_supported():
|
||||||
@ -477,7 +479,15 @@ class KeepalivedManager(object):
|
|||||||
service_name=KEEPALIVED_SERVICE_NAME)
|
service_name=KEEPALIVED_SERVICE_NAME)
|
||||||
|
|
||||||
pm = self.get_process()
|
pm = self.get_process()
|
||||||
pm.disable(sig='15')
|
pm.disable(sig=str(int(signal.SIGTERM)))
|
||||||
|
try:
|
||||||
|
utils.wait_until_true(lambda: not pm.active,
|
||||||
|
timeout=SIGTERM_TIMEOUT)
|
||||||
|
except utils.WaitTimeout:
|
||||||
|
LOG.warning('Keepalived process %s did not finish after SIGTERM '
|
||||||
|
'signal in %s seconds, sending SIGKILL signal',
|
||||||
|
pm.pid, SIGTERM_TIMEOUT)
|
||||||
|
pm.disable(sig=str(int(signal.SIGKILL)))
|
||||||
|
|
||||||
def check_processes(self):
|
def check_processes(self):
|
||||||
keepalived_pm = self.get_process()
|
keepalived_pm = self.get_process()
|
||||||
|
@ -14,13 +14,16 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
import signal
|
||||||
import textwrap
|
import textwrap
|
||||||
from unittest import mock
|
from unittest import mock
|
||||||
|
|
||||||
from neutron_lib import constants as n_consts
|
from neutron_lib import constants as n_consts
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
|
from oslo_utils import uuidutils
|
||||||
import testtools
|
import testtools
|
||||||
|
|
||||||
|
from neutron.agent.linux import external_process
|
||||||
from neutron.agent.linux import keepalived
|
from neutron.agent.linux import keepalived
|
||||||
from neutron.conf.agent.l3 import config as l3_config
|
from neutron.conf.agent.l3 import config as l3_config
|
||||||
from neutron.tests import base
|
from neutron.tests import base
|
||||||
@ -589,3 +592,40 @@ ping6 -c 1 -w 1 2001:db8::1 1>/dev/null || exit 1""",
|
|||||||
with mock.patch.object(keepalived, 'file_utils') as patched_utils:
|
with mock.patch.object(keepalived, 'file_utils') as patched_utils:
|
||||||
ts.write_check_script()
|
ts.write_check_script()
|
||||||
patched_utils.replace_file.assert_not_called()
|
patched_utils.replace_file.assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
|
class KeepalivedManagerTestCase(base.BaseTestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super().setUp()
|
||||||
|
self.mock_config = mock.Mock()
|
||||||
|
self.mock_config.AGENT.check_child_processes_interval = False
|
||||||
|
self.process_monitor = external_process.ProcessMonitor(
|
||||||
|
self.mock_config, mock.ANY)
|
||||||
|
self.uuid = uuidutils.generate_uuid()
|
||||||
|
self.process_monitor.register(
|
||||||
|
self.uuid, keepalived.KEEPALIVED_SERVICE_NAME, mock.ANY)
|
||||||
|
self.keepalived_manager = keepalived.KeepalivedManager(
|
||||||
|
self.uuid, self.mock_config, self.process_monitor, mock.ANY)
|
||||||
|
self.mock_get_process = mock.patch.object(self.keepalived_manager,
|
||||||
|
'get_process')
|
||||||
|
|
||||||
|
def test_destroy(self):
|
||||||
|
mock_get_process = self.mock_get_process.start()
|
||||||
|
process = mock.Mock()
|
||||||
|
mock_get_process.return_value = process
|
||||||
|
process.active = False
|
||||||
|
self.keepalived_manager.disable()
|
||||||
|
process.disable.assert_called_once_with(
|
||||||
|
sig=str(int(signal.SIGTERM)))
|
||||||
|
|
||||||
|
def test_destroy_force(self):
|
||||||
|
mock_get_process = self.mock_get_process.start()
|
||||||
|
with mock.patch.object(keepalived, 'SIGTERM_TIMEOUT', 0):
|
||||||
|
process = mock.Mock()
|
||||||
|
mock_get_process.return_value = process
|
||||||
|
process.active = True
|
||||||
|
self.keepalived_manager.disable()
|
||||||
|
process.disable.assert_has_calls([
|
||||||
|
mock.call(sig=str(int(signal.SIGTERM))),
|
||||||
|
mock.call(sig=str(int(signal.SIGKILL)))])
|
||||||
|
Loading…
Reference in New Issue
Block a user