]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Start linuxbridge neutron agent using a launcher
authorElena Ezhova <eezhova@mirantis.com>
Thu, 4 Jun 2015 14:00:13 +0000 (17:00 +0300)
committerElena Ezhova <eezhova@mirantis.com>
Fri, 5 Jun 2015 09:31:09 +0000 (12:31 +0300)
This change ports linuxbridge neutron agent on common/service code
that will allow to handle termination signals (SIGHUP, SIGTERM, SIGINT).

Note that this patch allows changing only logging options.
All other config options are not handled explicitly and changing
them using SIGHUP can lead to unpredictable circumstances.
So, until changing other options is handled it is highly recommended
to use SIGHUP for changing ONLY logging options.

DocImpact
Change-Id: I1d834e0683b04111ef04c148cbd8d4acf2964065
Closes-Bug: #1461539

etc/neutron/plugins/linuxbridge/linuxbridge_conf.ini
neutron/plugins/linuxbridge/agent/linuxbridge_neutron_agent.py
neutron/plugins/linuxbridge/common/config.py
neutron/tests/unit/plugins/linuxbridge/agent/test_linuxbridge_neutron_agent.py

index dac338b868f415c77d2116e9650255b230360578..b25d02916d5b70561bb36691de05360dfed88a25 100644 (file)
 # rpc_support_old_agents = False
 # Example: rpc_support_old_agents = True
 
+# (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
index 604cf73c43855631d588347c318f509cb79b8128..2cf116619e2bfb81a106275db02971a72a90b2b1 100644 (file)
@@ -44,6 +44,7 @@ from neutron.common import utils as q_utils
 from neutron import context
 from neutron.i18n import _LE, _LI, _LW
 from neutron.openstack.common import loopingcall
+from neutron.openstack.common import service
 from neutron.plugins.common import constants as p_const
 from neutron.plugins.linuxbridge.common import config  # noqa
 from neutron.plugins.linuxbridge.common import constants as lconst
@@ -749,12 +750,26 @@ class LinuxBridgeRpcCallbacks(sg_rpc.SecurityGroupAgentRpcCallbackMixin,
             getattr(self, method)(context, values)
 
 
-class LinuxBridgeNeutronAgentRPC(object):
+class LinuxBridgeNeutronAgentRPC(service.Service):
 
-    def __init__(self, interface_mappings, polling_interval):
+    def __init__(self, interface_mappings, polling_interval,
+                 quitting_rpc_timeout):
+        """Constructor.
+
+        :param interface_mappings: dict mapping physical_networks to
+               physical_interfaces.
+        :param polling_interval: interval (secs) to poll DB.
+        :param quitting_rpc_timeout: timeout in seconds for rpc calls after
+               stop is called.
+        """
+        super(LinuxBridgeNeutronAgentRPC, self).__init__()
+        self.interface_mappings = interface_mappings
         self.polling_interval = polling_interval
-        self.setup_linux_bridge(interface_mappings)
-        configurations = {'interface_mappings': interface_mappings}
+        self.quitting_rpc_timeout = quitting_rpc_timeout
+
+    def start(self):
+        self.setup_linux_bridge(self.interface_mappings)
+        configurations = {'interface_mappings': self.interface_mappings}
         if self.br_mgr.vxlan_mode != lconst.VXLAN_NONE:
             configurations['tunneling_ip'] = self.br_mgr.local_ip
             configurations['tunnel_types'] = [p_const.TYPE_VXLAN]
@@ -774,7 +789,17 @@ class LinuxBridgeNeutronAgentRPC(object):
         self.sg_plugin_rpc = sg_rpc.SecurityGroupServerRpcApi(topics.PLUGIN)
         self.sg_agent = sg_rpc.SecurityGroupAgentRpc(self.context,
                 self.sg_plugin_rpc)
-        self.setup_rpc(interface_mappings.values())
+        self.setup_rpc(self.interface_mappings.values())
+        self.daemon_loop()
+
+    def stop(self, graceful=True):
+        LOG.info(_LI("Stopping linuxbridge agent."))
+        if graceful and self.quitting_rpc_timeout:
+            self.set_rpc_timeout(self.quitting_rpc_timeout)
+        super(LinuxBridgeNeutronAgentRPC, self).stop(graceful)
+
+    def reset(self):
+        common_config.setup_logging()
 
     def _report_state(self):
         try:
@@ -1005,6 +1030,11 @@ class LinuxBridgeNeutronAgentRPC(object):
                           {'polling_interval': self.polling_interval,
                            'elapsed': elapsed})
 
+    def set_rpc_timeout(self, timeout):
+        for rpc_api in (self.plugin_rpc, self.sg_plugin_rpc,
+                        self.state_rpc):
+            rpc_api.client.timeout = timeout
+
 
 def main():
     common_config.init(sys.argv[1:])
@@ -1020,11 +1050,13 @@ def main():
     LOG.info(_LI("Interface mappings: %s"), interface_mappings)
 
     polling_interval = cfg.CONF.AGENT.polling_interval
+    quitting_rpc_timeout = cfg.CONF.AGENT.quitting_rpc_timeout
     agent = LinuxBridgeNeutronAgentRPC(interface_mappings,
-                                       polling_interval)
+                                       polling_interval,
+                                       quitting_rpc_timeout)
     LOG.info(_LI("Agent initialized successfully, now running... "))
-    agent.daemon_loop()
-    sys.exit(0)
+    launcher = service.launch(agent)
+    launcher.wait()
 
 
 if __name__ == "__main__":
index 90c6548dc8331986b647348f7148b447620a8cc2..fa1487c6b49f089507fc88fc19b8b3dd028175e0 100644 (file)
@@ -62,6 +62,10 @@ agent_opts = [
                       "polling for local device changes.")),
     cfg.BoolOpt('rpc_support_old_agents', default=False,
                 help=_("Enable server RPC compatibility with old agents")),
+    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")),
 ]
 
 
index 11e923fd3c0721069c8249e10d35f4bef1c8adc4..e1ae8315f3a86249163fe2302f76e296b0dc136a 100644 (file)
@@ -90,6 +90,7 @@ class TestLinuxBridgeAgent(base.BaseTestCase):
         cfg.CONF.set_default('firewall_driver',
                              'neutron.agent.firewall.NoopFirewallDriver',
                              group='SECURITYGROUP')
+        cfg.CONF.set_default('quitting_rpc_timeout', 10, 'AGENT')
         self.get_devices_p = mock.patch.object(ip_lib.IPWrapper, 'get_devices')
         self.get_devices = self.get_devices_p.start()
         self.get_devices.return_value = [ip_lib.IPDevice('eth77')]
@@ -100,7 +101,9 @@ class TestLinuxBridgeAgent(base.BaseTestCase):
         with mock.patch.object(linuxbridge_neutron_agent.LinuxBridgeManager,
                                'get_interface_by_ip', return_value=None):
             self.agent = linuxbridge_neutron_agent.LinuxBridgeNeutronAgentRPC(
-                {}, 0)
+                {}, 0, cfg.CONF.AGENT.quitting_rpc_timeout)
+            with mock.patch.object(self.agent, "daemon_loop"):
+                self.agent.start()
 
     def test_treat_devices_removed_with_existed_device(self):
         agent = self.agent
@@ -328,6 +331,20 @@ class TestLinuxBridgeAgent(base.BaseTestCase):
         agent.remove_port_binding.assert_called_with('net123', 'port123')
         self.assertFalse(agent.plugin_rpc.update_device_up.called)
 
+    def test_set_rpc_timeout(self):
+        self.agent.stop()
+        for rpc_client in (self.agent.plugin_rpc.client,
+                           self.agent.sg_plugin_rpc.client,
+                           self.agent.state_rpc.client):
+            self.assertEqual(cfg.CONF.AGENT.quitting_rpc_timeout,
+                             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.stop()
+            self.assertFalse(mock_set_rpc.called)
+
 
 class TestLinuxBridgeManager(base.BaseTestCase):
     def setUp(self):