]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Enhance wsgi to listen on ipv6 address
authorDavanum Srinivas <dims@linux.vnet.ibm.com>
Thu, 10 Jan 2013 16:26:25 +0000 (11:26 -0500)
committerDavanum Srinivas <dims@linux.vnet.ibm.com>
Tue, 22 Jan 2013 04:07:20 +0000 (23:07 -0500)
Check if the hostname is ipv6 and set the family appropriately.
Picked up the code snippet from glance to determine the address_family
per markmclain's comment
Picked up some code from nova as well to get the test case running
properly

Fixes LP# 1101341

Change-Id: I67166dc030e4ea0dd82888abfbc9db555747de27

quantum/tests/unit/test_wsgi.py [new file with mode: 0644]
quantum/wsgi.py

diff --git a/quantum/tests/unit/test_wsgi.py b/quantum/tests/unit/test_wsgi.py
new file mode 100644 (file)
index 0000000..45dedc1
--- /dev/null
@@ -0,0 +1,69 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 OpenStack LLC.
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+import mock
+import socket
+
+import unittest2 as unittest
+
+from quantum import wsgi
+
+
+class TestWSGIServer(unittest.TestCase):
+    """WSGI server tests."""
+
+    def test_start_random_port(self):
+        server = wsgi.Server("test_random_port")
+        server.start(None, 0, host="127.0.0.1")
+        self.assertNotEqual(0, server.port)
+        server.stop()
+        server.wait()
+
+    def test_start_random_port_with_ipv6(self):
+        server = wsgi.Server("test_random_port")
+        server.start(None, 0, host="::1")
+        self.assertEqual("::1", server.host)
+        self.assertNotEqual(0, server.port)
+        server.stop()
+        server.wait()
+
+
+class TestWSGIServer2(unittest.TestCase):
+    def setUp(self):
+        self.eventlet_p = mock.patch.object(wsgi, 'eventlet')
+        self.eventlet = self.eventlet_p.start()
+        self.server = wsgi.Server("test_app")
+
+    def tearDown(self):
+        self.eventlet_p.stop()
+
+    def test_ipv6_with_link_local_start(self):
+        mock_app = mock.Mock()
+        with mock.patch.object(self.server, 'pool') as pool:
+            self.server.start(mock_app,
+                              0,
+                              host="fe80::204:acff:fe96:da87%eth0")
+            self.eventlet.assert_has_calls([
+                mock.call.listen(('fe80::204:acff:fe96:da87%eth0', 0, 0, 2),
+                                 backlog=128,
+                                 family=10)
+            ])
+            pool.spawn.assert_has_calls([mock.call(
+                self.server._run,
+                mock_app,
+                self.eventlet.listen.mock_calls[0].return_value)
+            ])
index afef2db412a11a64ef91883b01013ce1ab725bdb..c9e6a5219f3e1e641640a1f315efcc44dbe57683 100644 (file)
@@ -18,6 +18,7 @@
 """
 Utility methods for working with WSGI servers
 """
+import socket
 import sys
 from xml.dom import minidom
 from xml.parsers import expat
@@ -51,8 +52,40 @@ class Server(object):
 
     def start(self, application, port, host='0.0.0.0', backlog=128):
         """Run a WSGI server with the given application."""
-        socket = eventlet.listen((host, port), backlog=backlog)
-        self.pool.spawn_n(self._run, application, socket)
+        self._host = host
+        self._port = port
+
+        # TODO(dims): eventlet's green dns/socket module does not actually
+        # support IPv6 in getaddrinfo(). We need to get around this in the
+        # future or monitor upstream for a fix
+        try:
+            info = socket.getaddrinfo(self._host,
+                                      self._port,
+                                      socket.AF_UNSPEC,
+                                      socket.SOCK_STREAM)[0]
+            family = info[0]
+            bind_addr = info[-1]
+
+            self._socket = eventlet.listen(bind_addr,
+                                           family=family,
+                                           backlog=backlog)
+        except:
+            LOG.exception(_("Unable to listen on %(host)s:%(port)s") %
+                          {'host': host, 'port': port})
+            sys.exit(1)
+
+        self._server = self.pool.spawn(self._run, application, self._socket)
+
+    @property
+    def host(self):
+        return self._socket.getsockname()[0] if self._socket else self._host
+
+    @property
+    def port(self):
+        return self._socket.getsockname()[1] if self._socket else self._port
+
+    def stop(self):
+        self._server.kill()
 
     def wait(self):
         """Wait until all servers have completed running."""