Merge pull request #353 from minrk/try-localhost

Ensure that we can bind and connect to localhost
This commit is contained in:
Min RK
2016-01-20 15:37:42 +01:00
5 changed files with 47 additions and 11 deletions

View File

@@ -50,7 +50,7 @@ from ._data import DATA_FILES_PATH
from .log import CoroutineLogFormatter, log_request
from .traitlets import URLPrefix, Command
from .utils import (
url_path_join,
url_path_join, localhost,
ISO8601_ms, ISO8601_s,
)
# classes for config
@@ -260,7 +260,7 @@ class JupyterHub(Application):
token = orm.new_token()
return token
proxy_api_ip = Unicode('localhost', config=True,
proxy_api_ip = Unicode(localhost(), config=True,
help="The ip for the proxy API handlers"
)
proxy_api_port = Integer(config=True,
@@ -272,7 +272,7 @@ class JupyterHub(Application):
hub_port = Integer(8081, config=True,
help="The port for this process"
)
hub_ip = Unicode('localhost', config=True,
hub_ip = Unicode(localhost(), config=True,
help="The ip for this process"
)

View File

@@ -26,7 +26,7 @@ from sqlalchemy import create_engine
from .utils import (
random_port, url_path_join, wait_for_server, wait_for_http_server,
new_token, hash_token, compare_token,
new_token, hash_token, compare_token, localhost,
)
@@ -78,7 +78,7 @@ class Server(Base):
ip = self.ip
if ip in {'', '0.0.0.0'}:
# when listening on all interfaces, connect to localhost
ip = 'localhost'
ip = localhost()
return "{proto}://{ip}:{port}".format(
proto=self.proto,
ip=ip,
@@ -109,12 +109,12 @@ class Server(Base):
if http:
yield wait_for_http_server(self.url, timeout=timeout)
else:
yield wait_for_server(self.ip or 'localhost', self.port, timeout=timeout)
yield wait_for_server(self.ip or localhost(), self.port, timeout=timeout)
def is_up(self):
"""Is the server accepting connections?"""
try:
socket.create_connection((self.ip or 'localhost', self.port))
socket.create_connection((self.ip or localhost(), self.port))
except socket.error as e:
if e.errno == errno.ENETUNREACH:
try:

View File

@@ -22,7 +22,7 @@ from traitlets import (
)
from .traitlets import Command
from .utils import random_port
from .utils import random_port, localhost
class Spawner(LoggingConfigurable):
"""Base class for spawning single-user notebook servers.
@@ -41,7 +41,7 @@ class Spawner(LoggingConfigurable):
hub = Any()
authenticator = Any()
api_token = Unicode()
ip = Unicode('localhost', config=True,
ip = Unicode(localhost(), config=True,
help="The IP address (or hostname) the single-user server should listen on"
)
start_timeout = Integer(60, config=True,

View File

@@ -17,6 +17,7 @@ from ..spawner import LocalProcessSpawner
from ..app import JupyterHub
from ..auth import PAMAuthenticator
from .. import orm
from ..utils import localhost
from pamela import PAMError
@@ -108,7 +109,7 @@ class MockHub(JupyterHub):
db_file = None
def _ip_default(self):
return 'localhost'
return localhost()
def _authenticator_class_default(self):
return MockPAMAuthenticator

View File

@@ -6,10 +6,12 @@
from binascii import b2a_hex
import errno
import hashlib
from hmac import compare_digest
import os
import socket
from threading import Thread
import uuid
from hmac import compare_digest
import warnings
from tornado import web, gen, ioloop
from tornado.httpclient import AsyncHTTPClient, HTTPError
@@ -192,3 +194,36 @@ def url_path_join(*pieces):
result = '/'
return result
def localhost():
"""Return localhost or 127.0.0.1"""
if hasattr(localhost, '_localhost'):
return localhost._localhost
binder = connector = None
try:
binder = socket.socket()
binder.bind(('localhost', 0))
binder.listen(1)
port = binder.getsockname()[1]
def accept():
try:
conn, addr = binder.accept()
except ConnectionAbortedError:
pass
else:
conn.close()
t = Thread(target=accept)
t.start()
connector = socket.create_connection(('localhost', port), timeout=10)
t.join(timeout=10)
except (socket.error, socket.gaierror) as e:
warnings.warn("localhost doesn't appear to work, using 127.0.0.1\n%s" % e, RuntimeWarning)
localhost._localhost = '127.0.0.1'
else:
localhost._localhost = 'localhost'
finally:
if binder:
binder.close()
if connector:
connector.close()
return localhost._localhost