-# portions extracted from ipaddresslib by Autonomous Zone Industries, LGPL (author: Greg Smith)
-# portions adapted from nattraverso.ipdiscover
-# portions authored by Brian Warner, working for Allmydata
-# most recent version authored by Zooko O'Whielacronx, working for Allmydata
-
# from the Python Standard Library
-import os, re, socket, sys
+import os, re, socket, sys, subprocess
# from Twisted
-from twisted.internet import defer
-from twisted.internet import reactor
+from twisted.internet import defer, threads, reactor
from twisted.internet.protocol import DatagramProtocol
-from twisted.internet.utils import getProcessOutput
from twisted.python.procutils import which
from twisted.python import log
-# from allmydata.util
-import observer
-
try:
import resource
def increase_rlimits():
# who knows what. It isn't very important, so log it and continue
log.err()
except ImportError:
- def increase_rlimits():
+ def _increase_rlimits():
# TODO: implement this for Windows. Although I suspect the
# solution might be "be running under the iocp reactor and
# make this function be a no-op".
pass
+ # pyflakes complains about two 'def FOO' statements in the same time,
+ # since one might be shadowing the other. This hack appeases pyflakes.
+ increase_rlimits = _increase_rlimits
-def get_local_addresses_async(target='A.ROOT-SERVERS.NET'):
+
+def get_local_addresses_async(target="198.41.0.4"): # A.ROOT-SERVERS.NET
"""
Return a Deferred that fires with a list of IPv4 addresses (as dotted-quad
strings) that are currently configured on this host, sorted in descending
try:
target_ipaddr = socket.gethostbyname(target)
except socket.gaierror:
- # DNS isn't running
+ # DNS isn't running, or somehow we encountered an error
+
+ # note: if an interface is configured and up, but nothing is
+ # connected to it, gethostbyname("A.ROOT-SERVERS.NET") will take 20
+ # seconds to raise socket.gaierror . This is synchronous and occurs
+ # for each node being started, so users of
+ # test.common.SystemTestMixin (like test_system) will see something
+ # like 120s of delay, which may be enough to hit the default trial
+ # timeouts. For that reason, get_local_addresses_async() was changed
+ # to default to the numerical ip address for A.ROOT-SERVERS.NET, to
+ # avoid this DNS lookup. This also makes node startup fractionally
+ # faster.
return None
udpprot = DatagramProtocol()
port = reactor.listenUDP(0, udpprot)
"linux-i386": "linux", # redhat
"linux-ppc": "linux", # redhat
"linux2": "linux", # debian
+ "linux3": "linux", # debian
"win32": "win32",
"irix6-n32": "irix",
"irix6-n64": "irix",
"irix6": "irix",
"openbsd2": "bsd",
+ "openbsd3": "bsd",
+ "openbsd4": "bsd",
"darwin": "bsd", # Mac OS X
"freebsd4": "bsd",
"freebsd5": "bsd",
+ "freebsd6": "bsd",
+ "freebsd7": "bsd",
+ "freebsd8": "bsd",
+ "freebsd9": "bsd",
"netbsd1": "bsd",
+ "netbsd2": "bsd",
+ "netbsd3": "bsd",
+ "netbsd4": "bsd",
+ "netbsd5": "bsd",
+ "netbsd6": "bsd",
"sunos5": "sunos",
"cygwin": "cygwin",
}
# These work in Redhat 6.x and Debian 2.2 potato
_linux_path = '/sbin/ifconfig'
-_linux_re = re.compile('^\s*inet addr:(?P<address>\d+\.\d+\.\d+\.\d+)\s.+$', flags=re.M|re.I|re.S)
+_linux_re = re.compile('^\s*inet [a-zA-Z]*:?(?P<address>\d+\.\d+\.\d+\.\d+)\s.+$', flags=re.M|re.I|re.S)
# NetBSD 1.4 (submitted by Rhialto), Darwin, Mac OS X
_netbsd_path = '/sbin/ifconfig'
_netbsd_args = ('-a',)
-_netbsd_re = re.compile('^\s+inet (?P<address>\d+\.\d+\.\d+\.\d+)\s.+$', flags=re.M|re.I|re.S)
+_netbsd_re = re.compile('^\s+inet [a-zA-Z]*:?(?P<address>\d+\.\d+\.\d+\.\d+)\s.+$', flags=re.M|re.I|re.S)
# Irix 6.5
_irix_path = '/usr/etc/ifconfig'
# Solaris 2.x
_sunos_path = '/usr/sbin/ifconfig'
-class SequentialTrier(object):
- """ I hold a list of executables to try and try each one in turn
- until one gives me a list of IP addresses."""
-
- def __init__(self, exebasename, args, regex):
- assert not os.path.isabs(exebasename)
- self.exes_left_to_try = which(exebasename)
- self.exes_left_to_try.reverse()
- self.args = args
- self.regex = regex
- self.o = observer.OneShotObserverList()
- self._try_next()
-
- def _try_next(self):
- if not self.exes_left_to_try:
- self.o.fire(None)
- else:
- exe = self.exes_left_to_try.pop()
- d2 = _query(exe, self.args, self.regex)
-
- def cb(res):
- if res:
- self.o.fire(res)
- else:
- self._try_next()
-
- def eb(why):
- self._try_next()
-
- d2.addCallbacks(cb, eb)
-
- def when_tried(self):
- return self.o.when_fired()
# k: platform string as provided in the value of _platform_map
# v: tuple of (path_to_tool, args, regex,)
"irix": (_irix_path, _netbsd_args, _netbsd_re,),
"sunos": (_sunos_path, _netbsd_args, _netbsd_re,),
}
+
def _find_addresses_via_config():
+ return threads.deferToThread(_synchronously_find_addresses_via_config)
+
+def _synchronously_find_addresses_via_config():
# originally by Greg Smith, hacked by Zooko to conform to Brian's API
platform = _platform_map.get(sys.platform)
if os.path.isabs(pathtotool):
return _query(pathtotool, args, regex)
else:
- return SequentialTrier(pathtotool, args, regex).when_tried()
+ exes_to_try = which(pathtotool)
+ for exe in exes_to_try:
+ try:
+ addresses = _query(exe, args, regex)
+ except Exception:
+ addresses = []
+ if addresses:
+ return addresses
+ return []
def _query(path, args, regex):
- d = getProcessOutput(path, args)
- def _parse(output):
- addresses = []
- outputsplit = output.split('\n')
- for outline in outputsplit:
- m = regex.match(outline)
- if m:
- addr = m.groupdict()['address']
- if addr not in addresses:
- addresses.append(addr)
+ env = {'LANG': 'en_US.UTF-8'}
+ p = subprocess.Popen([path] + list(args), stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env)
+ (output, err) = p.communicate()
- return addresses
- d.addCallback(_parse)
- return d
+ addresses = []
+ outputsplit = output.split('\n')
+ for outline in outputsplit:
+ m = regex.match(outline)
+ if m:
+ addr = m.groupdict()['address']
+ if addr not in addresses:
+ addresses.append(addr)
+
+ return addresses
def _cygwin_hack_find_addresses(target):
addresses = []