Merge "Stop metadata proxy gracefully" into stable/ussuri

This commit is contained in:
Zuul 2021-03-09 20:23:18 +00:00 committed by Gerrit Code Review
commit 9e050f5648
3 changed files with 62 additions and 5 deletions

View File

@ -16,6 +16,7 @@
import grp import grp
import os import os
import pwd import pwd
import signal
from neutron_lib.callbacks import events from neutron_lib.callbacks import events
from neutron_lib.callbacks import registry from neutron_lib.callbacks import registry
@ -30,10 +31,13 @@ from neutron.agent.l3 import ha_router
from neutron.agent.l3 import namespaces from neutron.agent.l3 import namespaces
from neutron.agent.linux import external_process from neutron.agent.linux import external_process
from neutron.agent.linux import utils as linux_utils from neutron.agent.linux import utils as linux_utils
from neutron.common import utils as common_utils
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
SIGTERM_TIMEOUT = 5
METADATA_SERVICE_NAME = 'metadata-proxy' METADATA_SERVICE_NAME = 'metadata-proxy'
HAPROXY_SERVICE = 'haproxy' HAPROXY_SERVICE = 'haproxy'
@ -246,10 +250,19 @@ class MetadataDriver(object):
monitor.unregister(uuid, METADATA_SERVICE_NAME) monitor.unregister(uuid, METADATA_SERVICE_NAME)
pm = cls._get_metadata_proxy_process_manager(uuid, conf, pm = cls._get_metadata_proxy_process_manager(uuid, conf,
ns_name=ns_name) ns_name=ns_name)
pm.disable() pm.disable(sig=str(int(signal.SIGTERM)))
try:
common_utils.wait_until_true(lambda: not pm.active,
timeout=SIGTERM_TIMEOUT)
except common_utils.WaitTimeout:
LOG.warning('Metadata 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)))
# Delete metadata proxy config file # Delete metadata proxy config and PID files.
HaproxyConfigurator.cleanup_config_file(uuid, cfg.CONF.state_path) HaproxyConfigurator.cleanup_config_file(uuid, cfg.CONF.state_path)
linux_utils.delete_if_exists(pm.get_pid_file_name(), run_as_root=True)
cls.monitors.pop(uuid, None) cls.monitors.pop(uuid, None)

View File

@ -16,6 +16,7 @@
import collections import collections
import copy import copy
import datetime import datetime
import signal
import sys import sys
import uuid import uuid
@ -792,7 +793,7 @@ class TestDhcpAgentEventHandler(base.BaseTestCase):
else: else:
self.external_process.assert_has_calls([ self.external_process.assert_has_calls([
self._process_manager_constructor_call(), self._process_manager_constructor_call(),
mock.call().disable()]) mock.call().disable(sig=str(int(signal.SIGTERM)))])
def test_enable_dhcp_helper_enable_metadata_isolated_network(self): def test_enable_dhcp_helper_enable_metadata_isolated_network(self):
self._enable_dhcp_helper(isolated_network, self._enable_dhcp_helper(isolated_network,
@ -911,7 +912,7 @@ class TestDhcpAgentEventHandler(base.BaseTestCase):
self.call_driver.assert_called_once_with('disable', fake_network) self.call_driver.assert_called_once_with('disable', fake_network)
self.external_process.assert_has_calls([ self.external_process.assert_has_calls([
self._process_manager_constructor_call(), self._process_manager_constructor_call(),
mock.call().disable()]) mock.call().disable(sig=str(int(signal.SIGTERM)))])
def test_disable_dhcp_helper_known_network_isolated_metadata(self): def test_disable_dhcp_helper_known_network_isolated_metadata(self):
self._disable_dhcp_helper_known_network(isolated_metadata=True) self._disable_dhcp_helper_known_network(isolated_metadata=True)
@ -940,7 +941,7 @@ class TestDhcpAgentEventHandler(base.BaseTestCase):
[mock.call.get_network_by_id(fake_network.id)]) [mock.call.get_network_by_id(fake_network.id)])
self.external_process.assert_has_calls([ self.external_process.assert_has_calls([
self._process_manager_constructor_call(), self._process_manager_constructor_call(),
mock.call().disable() mock.call().disable(sig=str(int(signal.SIGTERM)))
]) ])
def test_disable_dhcp_helper_driver_failure_isolated_metadata(self): def test_disable_dhcp_helper_driver_failure_isolated_metadata(self):

View File

@ -14,6 +14,7 @@
# under the License. # under the License.
import os import os
import signal
import mock import mock
from neutron_lib import constants from neutron_lib import constants
@ -24,6 +25,7 @@ from oslo_utils import uuidutils
from neutron.agent.l3 import agent as l3_agent from neutron.agent.l3 import agent as l3_agent
from neutron.agent.l3 import router_info from neutron.agent.l3 import router_info
from neutron.agent.linux import iptables_manager from neutron.agent.linux import iptables_manager
from neutron.agent.linux import utils as linux_utils
from neutron.agent.metadata import driver as metadata_driver from neutron.agent.metadata import driver as metadata_driver
from neutron.conf.agent import common as agent_config from neutron.conf.agent import common as agent_config
from neutron.conf.agent.l3 import config as l3_config from neutron.conf.agent.l3 import config as l3_config
@ -35,6 +37,12 @@ from neutron.tests.unit.agent.linux import test_utils
_uuid = uuidutils.generate_uuid _uuid = uuidutils.generate_uuid
class FakeL3NATAgent(object):
def __init__(self):
self.conf = cfg.CONF
class TestMetadataDriverRules(base.BaseTestCase): class TestMetadataDriverRules(base.BaseTestCase):
def test_metadata_nat_rules(self): def test_metadata_nat_rules(self):
@ -72,6 +80,11 @@ class TestMetadataDriverProcess(base.BaseTestCase):
mock.patch('neutron.agent.l3.agent.L3PluginApi').start() mock.patch('neutron.agent.l3.agent.L3PluginApi').start()
mock.patch('neutron.agent.l3.ha.AgentMixin' mock.patch('neutron.agent.l3.ha.AgentMixin'
'._init_ha_conf_path').start() '._init_ha_conf_path').start()
self.delete_if_exists = mock.patch.object(linux_utils,
'delete_if_exists')
self.mock_get_process = mock.patch.object(
metadata_driver.MetadataDriver,
'_get_metadata_proxy_process_manager')
l3_config.register_l3_agent_config_opts(l3_config.OPTS, cfg.CONF) l3_config.register_l3_agent_config_opts(l3_config.OPTS, cfg.CONF)
ha_conf.register_l3_agent_ha_opts() ha_conf.register_l3_agent_ha_opts()
@ -196,3 +209,33 @@ class TestMetadataDriverProcess(base.BaseTestCase):
mock.ANY, mock.ANY) mock.ANY, mock.ANY)
self.assertRaises(metadata_driver.InvalidUserOrGroupException, self.assertRaises(metadata_driver.InvalidUserOrGroupException,
config.create_config_file) config.create_config_file)
def test_destroy_monitored_metadata_proxy(self):
delete_if_exists = self.delete_if_exists.start()
mproxy_process = mock.Mock(
active=False, get_pid_file_name=mock.Mock(return_value='pid_file'))
mock_get_process = self.mock_get_process.start()
mock_get_process.return_value = mproxy_process
driver = metadata_driver.MetadataDriver(FakeL3NATAgent())
driver.destroy_monitored_metadata_proxy(mock.Mock(), 'uuid', 'conf',
'ns_name')
mproxy_process.disable.assert_called_once_with(
sig=str(int(signal.SIGTERM)))
delete_if_exists.assert_has_calls([
mock.call('pid_file', run_as_root=True)])
def test_destroy_monitored_metadata_proxy_force(self):
delete_if_exists = self.delete_if_exists.start()
mproxy_process = mock.Mock(
active=True, get_pid_file_name=mock.Mock(return_value='pid_file'))
mock_get_process = self.mock_get_process.start()
mock_get_process.return_value = mproxy_process
driver = metadata_driver.MetadataDriver(FakeL3NATAgent())
with mock.patch.object(metadata_driver, 'SIGTERM_TIMEOUT', 0):
driver.destroy_monitored_metadata_proxy(mock.Mock(), 'uuid',
'conf', 'ns_name')
mproxy_process.disable.assert_has_calls([
mock.call(sig=str(int(signal.SIGTERM))),
mock.call(sig=str(int(signal.SIGKILL)))])
delete_if_exists.assert_has_calls([
mock.call('pid_file', run_as_root=True)])