Merge pull request #142 from tahoe-lafs/754.location-AUTO.2

Allow combining autodetected and statically configured locations
This commit is contained in:
Daira Hopwood 2015-02-10 18:28:09 +00:00
commit 2d9af506f1
3 changed files with 66 additions and 30 deletions

View File

@ -4,7 +4,7 @@
Configuring a Tahoe-LAFS node Configuring a Tahoe-LAFS node
============================= =============================
1. `Node Types`_ 1. `Node Types`_
2. `Overall Node Configuration`_ 2. `Overall Node Configuration`_
3. `Client Configuration`_ 3. `Client Configuration`_
4. `Storage Server Configuration`_ 4. `Storage Server Configuration`_
@ -159,6 +159,11 @@ set the ``tub.location`` option described below.
this when using a Tor proxy to avoid revealing your actual IP address this when using a Tor proxy to avoid revealing your actual IP address
through the Introducer announcement. through the Introducer announcement.
If ``tub.location`` is specified, by default it entirely replaces the
automatically determined set of IP addresses. To include the automatically
determined addresses as well as the specified ones, include the uppercase
string "``AUTO``" in the list.
The value is a comma-separated string of host:port location hints, like The value is a comma-separated string of host:port location hints, like
this:: this::
@ -177,6 +182,11 @@ set the ``tub.location`` option described below.
tub.port = 8098 tub.port = 8098
tub.location = tahoe.example.com:8098 tub.location = tahoe.example.com:8098
* Use a DNS name but also include the default set of addresses::
tub.port = 8098
tub.location = tahoe.example.com:8098,AUTO
* Run a node behind a firewall (which has an external IP address) that * Run a node behind a firewall (which has an external IP address) that
has been configured to forward port 7912 to our internal node's port has been configured to forward port 7912 to our internal node's port
8098:: 8098::

View File

@ -326,7 +326,6 @@ class Node(service.MultiService):
service.MultiService.startService(self) service.MultiService.startService(self)
d = defer.succeed(None) d = defer.succeed(None)
d.addCallback(lambda res: iputil.get_local_addresses_async())
d.addCallback(self._setup_tub) d.addCallback(self._setup_tub)
def _ready(res): def _ready(res):
self.log("%s running" % self.NODETYPE) self.log("%s running" % self.NODETYPE)
@ -389,7 +388,7 @@ class Node(service.MultiService):
def log(self, *args, **kwargs): def log(self, *args, **kwargs):
return log.msg(*args, **kwargs) return log.msg(*args, **kwargs)
def _setup_tub(self, local_addresses): def _setup_tub(self, ign):
# we can't get a dynamically-assigned portnum until our Tub is # we can't get a dynamically-assigned portnum until our Tub is
# running, which means after startService. # running, which means after startService.
l = self.tub.getListeners()[0] l = self.tub.getListeners()[0]
@ -398,13 +397,29 @@ class Node(service.MultiService):
# next time # next time
fileutil.write_atomically(self._portnumfile, "%d\n" % portnum, mode="") fileutil.write_atomically(self._portnumfile, "%d\n" % portnum, mode="")
base_location = ",".join([ "%s:%d" % (addr, portnum) location = self.get_config("node", "tub.location", "AUTO")
for addr in local_addresses ])
location = self.get_config("node", "tub.location", base_location)
self.log("Tub location set to %s" % location)
self.tub.setLocation(location)
return self.tub # Replace the location "AUTO", if present, with the detected local addresses.
split_location = location.split(",")
if "AUTO" in split_location:
d = iputil.get_local_addresses_async()
def _add_local(local_addresses):
while "AUTO" in split_location:
split_location.remove("AUTO")
split_location.extend([ "%s:%d" % (addr, portnum)
for addr in local_addresses ])
return ",".join(split_location)
d.addCallback(_add_local)
else:
d = defer.succeed(location)
def _got_location(location):
self.log("Tub location set to %s" % (location,))
self.tub.setLocation(location)
return self.tub
d.addCallback(_got_location)
return d
def when_tub_ready(self): def when_tub_ready(self):
return self._tub_ready_observerlist.when_fired() return self._tub_ready_observerlist.when_fired()

View File

@ -9,7 +9,7 @@ from mock import patch
from foolscap.api import flushEventualQueue from foolscap.api import flushEventualQueue
from twisted.application import service from twisted.application import service
from allmydata.node import Node, formatTimeTahoeStyle, MissingConfigEntry from allmydata.node import Node, formatTimeTahoeStyle, MissingConfigEntry
from allmydata.util import fileutil from allmydata.util import fileutil, iputil
import allmydata.test.common_util as testutil import allmydata.test.common_util as testutil
class LoggingMultiService(service.MultiService): class LoggingMultiService(service.MultiService):
@ -33,44 +33,55 @@ class TestCase(testutil.SignalMixin, unittest.TestCase):
d.addCallback(flushEventualQueue) d.addCallback(flushEventualQueue)
return d return d
def test_location(self): def _test_location(self, basedir, expected_addresses, tub_port=None, tub_location=None, local_addresses=None):
basedir = "test_node/test_location"
fileutil.make_dirs(basedir) fileutil.make_dirs(basedir)
f = open(os.path.join(basedir, 'tahoe.cfg'), 'wt') f = open(os.path.join(basedir, 'tahoe.cfg'), 'wt')
f.write("[node]\n") f.write("[node]\n")
f.write("tub.location = 1.2.3.4:5\n") if tub_port:
f.write("tub.port = %d\n" % (tub_port,))
if tub_location is not None:
f.write("tub.location = %s\n" % (tub_location,))
f.close() f.close()
if local_addresses:
self.patch(iputil, 'get_local_addresses_async', lambda target=None: defer.succeed(local_addresses))
n = TestNode(basedir) n = TestNode(basedir)
n.setServiceParent(self.parent) n.setServiceParent(self.parent)
d = n.when_tub_ready() d = n.when_tub_ready()
def _check_addresses(ignored_result): def _check_addresses(ignored_result):
furl = n.tub.registerReference(n) furl = n.tub.registerReference(n)
self.failUnless("1.2.3.4:5" in furl, furl) for address in expected_addresses:
self.failUnlessIn(address, furl)
d.addCallback(_check_addresses) d.addCallback(_check_addresses)
return d return d
def test_location1(self):
return self._test_location(basedir="test_node/test_location1",
expected_addresses=["192.0.2.0:1234"],
tub_location="192.0.2.0:1234")
def test_location2(self): def test_location2(self):
basedir = "test_node/test_location2" return self._test_location(basedir="test_node/test_location2",
fileutil.make_dirs(basedir) expected_addresses=["192.0.2.0:1234", "example.org:8091"],
f = open(os.path.join(basedir, 'tahoe.cfg'), 'wt') tub_location="192.0.2.0:1234,example.org:8091")
f.write("[node]\n")
f.write("tub.location = 1.2.3.4:5,example.org:8091\n")
f.close()
n = TestNode(basedir) def test_location_not_set(self):
n.setServiceParent(self.parent) """Checks the autogenerated furl when tub.location is not set."""
d = n.when_tub_ready() return self._test_location(basedir="test_node/test_location3",
expected_addresses=["127.0.0.1:1234", "192.0.2.0:1234"],
tub_port=1234,
local_addresses=["127.0.0.1", "192.0.2.0"])
def _check_addresses(ignored_result): def test_location_auto_and_explicit(self):
furl = n.tub.registerReference(n) """Checks the autogenerated furl when tub.location contains 'AUTO'."""
self.failUnless("1.2.3.4:5" in furl, furl) return self._test_location(basedir="test_node/test_location4",
self.failUnless("example.org:8091" in furl, furl) expected_addresses=["127.0.0.1:1234", "192.0.2.0:1234", "example.com:4321"],
tub_port=1234,
d.addCallback(_check_addresses) tub_location="AUTO,example.com:4321",
return d local_addresses=["127.0.0.1", "192.0.2.0", "example.com:4321"])
def test_tahoe_cfg_utf8(self): def test_tahoe_cfg_utf8(self):
basedir = "test_node/test_tahoe_cfg_utf8" basedir = "test_node/test_tahoe_cfg_utf8"