diff --git a/glance/cmd/__init__.py b/glance/cmd/__init__.py index e1aeec3bd1..e753f71c3d 100644 --- a/glance/cmd/__init__.py +++ b/glance/cmd/__init__.py @@ -13,6 +13,41 @@ # License for the specific language governing permissions and limitations # under the License. +import os +import sys + +import oslo.utils.strutils as strutils + from glance import i18n +try: + import dns # NOQA +except ImportError: + dnspython_installed = False +else: + dnspython_installed = True + + +def fix_greendns_ipv6(): + if dnspython_installed: + # All of this is because if dnspython is present in your environment + # then eventlet monkeypatches socket.getaddrinfo() with an + # implementation which doesn't work for IPv6. What we're checking here + # is that the magic environment variable was set when the import + # happened. + nogreendns = 'EVENTLET_NO_GREENDNS' + flag = os.environ.get(nogreendns, '') + if 'eventlet' in sys.modules and not strutils.bool_from_string(flag): + msg = i18n._("It appears that the eventlet module has been " + "imported prior to setting %s='yes'. It is currently " + "necessary to disable eventlet.greendns " + "if using ipv6 since eventlet.greendns currently " + "breaks with ipv6 addresses. Please ensure that " + "eventlet is not imported prior to this being set.") + raise ImportError(msg % (nogreendns)) + + os.environ[nogreendns] = 'yes' + + i18n.enable_lazy() +fix_greendns_ipv6() diff --git a/glance/tests/__init__.py b/glance/tests/__init__.py index b1f12689ad..557340aa49 100644 --- a/glance/tests/__init__.py +++ b/glance/tests/__init__.py @@ -13,6 +13,11 @@ # License for the specific language governing permissions and limitations # under the License. +import glance.cmd as glance_cmd + + +glance_cmd.fix_greendns_ipv6() + # See http://code.google.com/p/python-nose/issues/detail?id=373 # The code below enables tests to work with i18n _() blocks import six.moves.builtins as __builtin__ diff --git a/glance/tests/unit/common/test_wsgi_ipv6.py b/glance/tests/unit/common/test_wsgi_ipv6.py new file mode 100644 index 0000000000..1669170215 --- /dev/null +++ b/glance/tests/unit/common/test_wsgi_ipv6.py @@ -0,0 +1,74 @@ +# Copyright 2010-2014 OpenStack Foundation +# 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 subprocess + +from glance.tests import utils as test_utils + + +script = """ +import os +import sys +# Spoof module installed +sys.modules['%s'] = object +%s +os.environ['EVENTLET_NO_GREENDNS'] = '%s' +if 'eventlet' %s in sys.modules: + sys.exit(2) +try: + import glance.cmd +except ImportError: + sys.exit(%d) +else: + sys.exit(%d) +""" + +eventlet_no_dns = script % ('fake', '', 'yes', '', 1, 0) + +no_eventlet_no_greendns = script % ('dns', '', 'yes', '', 1, 0) + +eventlet_no_greendns = script % ('dns', 'import eventlet', 'yes', 'not', 1, 0) + +no_eventlet_greendns = script % ('dns', '', 'no', '', 1, 0) + +eventlet_greendns = script % ('dns', 'import eventlet', 'no', 'not', 0, 1) + + +class IPv6ServerTest(test_utils.BaseTestCase): + + def test_evnetlet_no_dnspython(self): + """Test eventlet imported but dnspython not installed""" + rc = subprocess.call(['python', '-c', eventlet_no_dns]) + self.assertEqual(0, rc) + + def test_no_eventlet_no_greendns(self): + """Test eventlet not imported with EVENTLET_NO_GREENDNS='yes'""" + rc = subprocess.call(['python', '-c', no_eventlet_no_greendns]) + self.assertEqual(0, rc) + + def test_eventlet_no_greendns(self): + """Test eventlet pre-imported with EVENTLET_NO_GREENDNS='yes'""" + rc = subprocess.call(['python', '-c', eventlet_no_greendns]) + self.assertEqual(0, rc) + + def test_no_eventlet_w_greendns(self): + """Test eventlet not imported with EVENTLET_NO_GREENDNS='no'""" + rc = subprocess.call(['python', '-c', no_eventlet_greendns]) + self.assertEqual(0, rc) + + def test_eventlet_w_greendns(self): + """Test eventlet pre-imported with EVENTLET_NO_GREENDNS='no'""" + rc = subprocess.call(['python', '-c', eventlet_greendns]) + self.assertEqual(0, rc)