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
(cherry picked from commit 2618acff51
)
This commit is contained in:
parent
ad0a77946c
commit
d1f5b6ff72
|
@ -15,6 +15,7 @@
|
|||
import errno
|
||||
import itertools
|
||||
import os
|
||||
import signal
|
||||
|
||||
import netaddr
|
||||
from neutron_lib import constants
|
||||
|
@ -39,6 +40,7 @@ GARP_PRIMARY_DELAY = 60
|
|||
HEALTH_CHECK_NAME = 'ha_health_check'
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
SIGTERM_TIMEOUT = 5
|
||||
|
||||
|
||||
def get_free_range(parent_range, excluded_ranges, size=PRIMARY_VIP_RANGE_SIZE):
|
||||
|
@ -457,7 +459,15 @@ class KeepalivedManager(object):
|
|||
service_name=KEEPALIVED_SERVICE_NAME)
|
||||
|
||||
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):
|
||||
keepalived_pm = self.get_process()
|
||||
|
|
|
@ -14,13 +14,16 @@
|
|||
#
|
||||
|
||||
import os
|
||||
import signal
|
||||
import textwrap
|
||||
from unittest import mock
|
||||
|
||||
from neutron_lib import constants as n_consts
|
||||
from oslo_config import cfg
|
||||
from oslo_utils import uuidutils
|
||||
import testtools
|
||||
|
||||
from neutron.agent.linux import external_process
|
||||
from neutron.agent.linux import keepalived
|
||||
from neutron.conf.agent.l3 import config as l3_config
|
||||
from neutron.tests import base
|
||||
|
@ -543,3 +546,40 @@ ping6 -c 1 -w 1 2001:db8::1 1>/dev/null || exit 1""",
|
|||
with mock.patch.object(keepalived, 'file_utils') as patched_utils:
|
||||
ts.write_check_script()
|
||||
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