From 7cd3d0c1b76dff9151f5cee34ea3e313c1b19ecd Mon Sep 17 00:00:00 2001 From: Jakub Libosvar Date: Fri, 30 Jan 2015 18:30:22 +0100 Subject: [PATCH] Decrease rpc timeout after agent receives SIGTERM The patch sets different timeout to rpc api objects in OVS agent after SIGTERM is received. Given timeout is configurable. This action prevents long waiting for rpc call() methods to timeout and decreases amount of time needed to successfully stopping OVS agent. DocImpact Closes-Bug: 1408334 Change-Id: I3026775e813a74bad9e0bca3be1f535212a2e417 (cherry picked from commit d3af7b0d2ebb2dd4da7e4a620eca8f554c124ec6) --- .../plugins/openvswitch/ovs_neutron_plugin.ini | 5 +++++ .../plugins/openvswitch/agent/ovs_neutron_agent.py | 14 +++++++++++++- neutron/plugins/openvswitch/common/config.py | 4 ++++ .../unit/openvswitch/test_ovs_neutron_agent.py | 13 +++++++++++++ 4 files changed, 35 insertions(+), 1 deletion(-) diff --git a/etc/neutron/plugins/openvswitch/ovs_neutron_plugin.ini b/etc/neutron/plugins/openvswitch/ovs_neutron_plugin.ini index 9c8e6b58894..45aa9451701 100644 --- a/etc/neutron/plugins/openvswitch/ovs_neutron_plugin.ini +++ b/etc/neutron/plugins/openvswitch/ovs_neutron_plugin.ini @@ -149,6 +149,11 @@ # # enable_distributed_routing = False +# (IntOpt) Set new timeout in seconds for new rpc calls after agent receives +# SIGTERM. If value is set to 0, rpc timeout won't be changed" +# +# quitting_rpc_timeout = 10 + [securitygroup] # Firewall driver for realizing neutron security group function. # firewall_driver = neutron.agent.firewall.NoopFirewallDriver diff --git a/neutron/plugins/openvswitch/agent/ovs_neutron_agent.py b/neutron/plugins/openvswitch/agent/ovs_neutron_agent.py index 68325a3ca5b..eb5efd5b1be 100644 --- a/neutron/plugins/openvswitch/agent/ovs_neutron_agent.py +++ b/neutron/plugins/openvswitch/agent/ovs_neutron_agent.py @@ -140,7 +140,8 @@ class OVSNeutronAgent(n_rpc.RpcCallback, ovsdb_monitor_respawn_interval=( constants.DEFAULT_OVSDBMON_RESPAWN), arp_responder=False, - use_veth_interconnection=False): + use_veth_interconnection=False, + quitting_rpc_timeout=None): '''Constructor. :param integ_br: name of the integration bridge. @@ -163,6 +164,8 @@ class OVSNeutronAgent(n_rpc.RpcCallback, supported. :param use_veth_interconnection: use veths instead of patch ports to interconnect the integration bridge to physical bridges. + :param quitting_rpc_timeout: timeout in seconds for rpc calls after + SIGTERM is received ''' super(OVSNeutronAgent, self).__init__() self.use_veth_interconnection = use_veth_interconnection @@ -253,6 +256,8 @@ class OVSNeutronAgent(n_rpc.RpcCallback, # The initialization is complete; we can start receiving messages self.connection.consume_in_threads() + self.quitting_rpc_timeout = quitting_rpc_timeout + def _report_state(self): # How many devices are likely used by a VM self.agent_state.get('configurations')['devices'] = ( @@ -1479,6 +1484,12 @@ class OVSNeutronAgent(n_rpc.RpcCallback, def _handle_sigterm(self, signum, frame): LOG.debug("Agent caught SIGTERM, quitting daemon loop.") self.run_daemon_loop = False + if self.quitting_rpc_timeout: + self.set_rpc_timeout(self.quitting_rpc_timeout) + + def set_rpc_timeout(self, timeout): + for rpc_api in (self.plugin_rpc, self.state_rpc): + rpc_api._client.timeout = timeout def create_agent_config_map(config): @@ -1506,6 +1517,7 @@ def create_agent_config_map(config): l2_population=config.AGENT.l2_population, arp_responder=config.AGENT.arp_responder, use_veth_interconnection=config.OVS.use_veth_interconnection, + quitting_rpc_timeout=config.AGENT.quitting_rpc_timeout ) # If enable_tunneling is TRUE, set tunnel_type to default to GRE diff --git a/neutron/plugins/openvswitch/common/config.py b/neutron/plugins/openvswitch/common/config.py index d9e0454839c..f3bb1e19100 100644 --- a/neutron/plugins/openvswitch/common/config.py +++ b/neutron/plugins/openvswitch/common/config.py @@ -94,6 +94,10 @@ agent_opts = [ "outgoing IP packet carrying GRE/VXLAN tunnel.")), cfg.BoolOpt('enable_distributed_routing', default=False, help=_("Make the l2 agent run in DVR mode.")), + cfg.IntOpt('quitting_rpc_timeout', default=10, + help=_("Set new timeout in seconds for new rpc calls after " + "agent receives SIGTERM. If value is set to 0, rpc " + "timeout won't be changed")) ] diff --git a/neutron/tests/unit/openvswitch/test_ovs_neutron_agent.py b/neutron/tests/unit/openvswitch/test_ovs_neutron_agent.py index 64ba72a9058..b2fafb9efd3 100644 --- a/neutron/tests/unit/openvswitch/test_ovs_neutron_agent.py +++ b/neutron/tests/unit/openvswitch/test_ovs_neutron_agent.py @@ -104,6 +104,7 @@ class TestOvsNeutronAgent(base.BaseTestCase): cfg.CONF.set_default('firewall_driver', 'neutron.agent.firewall.NoopFirewallDriver', group='SECURITYGROUP') + cfg.CONF.set_default('quitting_rpc_timeout', 10, 'AGENT') kwargs = ovs_neutron_agent.create_agent_config_map(cfg.CONF) class MockFixedIntervalLoopingCall(object): @@ -1403,6 +1404,18 @@ class TestOvsNeutronAgent(base.BaseTestCase): setup_int_br.assert_has_calls([mock.call()]) setup_phys_br.assert_has_calls([mock.call({})]) + def test_set_rpc_timeout(self): + self.agent._handle_sigterm(None, None) + for rpc_client in (self.agent.plugin_rpc._client, + self.agent.state_rpc._client): + self.assertEqual(10, rpc_client.timeout) + + def test_set_rpc_timeout_no_value(self): + self.agent.quitting_rpc_timeout = None + with mock.patch.object(self.agent, 'set_rpc_timeout') as mock_set_rpc: + self.agent._handle_sigterm(None, None) + self.assertFalse(mock_set_rpc.called) + class AncillaryBridgesTest(base.BaseTestCase):