mirror of
https://github.com/tahoe-lafs/tahoe-lafs.git
synced 2025-04-08 19:34:18 +00:00
Merge branch '2773-listen-port'
This adds several arguments to "tahoe create-node" and create-introducer: * --location=/--port=: always provided as a pair, directly set the listening port and the advertised location * --hostname=: provides the node's hostname so it doesn't have to crawl the network interfaces for IP addresses, when listening on TCP * --listen=: can only be "tcp" for now, but will soon be the way to enable automatic listener setup for Tor and I2P services This is a rebased and cleaned-up version of #336, which fixes a bunch of tests, and simplifies the argument validation slightly. closes tahoe-lafs/tahoe-lafs#336 closes ticket:2773
This commit is contained in:
commit
a8899c8fc3
@ -1,9 +1,10 @@
|
||||
import os
|
||||
from twisted.python.usage import UsageError
|
||||
from allmydata.scripts.common import BasedirOptions, NoDefaultBasedirOptions
|
||||
from allmydata.scripts.default_nodedir import _default_nodedir
|
||||
from allmydata.util.assertutil import precondition
|
||||
from allmydata.util.encodingutil import listdir_unicode, argv_to_unicode, quote_local_unicode_path
|
||||
from allmydata.util import fileutil
|
||||
from allmydata.util import fileutil, iputil
|
||||
|
||||
|
||||
dummy_tac = """
|
||||
@ -17,10 +18,50 @@ def write_tac(basedir, nodetype):
|
||||
fileutil.write(os.path.join(basedir, "tahoe-%s.tac" % (nodetype,)), dummy_tac)
|
||||
|
||||
|
||||
WHERE_OPTS = [
|
||||
("location", None, None, "Specify the location to advertise for this node."),
|
||||
("port", None, None, "Specify the server endpoint to listen on for this node."),
|
||||
]
|
||||
|
||||
def validate_where_options(o):
|
||||
# --location and --port: overrides all others, rejects all others
|
||||
if o['location'] and not o['port']:
|
||||
raise UsageError("--location must be used with --port")
|
||||
if o['port'] and not o['location']:
|
||||
raise UsageError("--port must be used with --location")
|
||||
|
||||
if o['location'] and o['port']:
|
||||
if o['hostname']:
|
||||
raise UsageError("--hostname cannot be used with --location/--port")
|
||||
# TODO: really, we should reject an explicit --listen= option (we
|
||||
# want them to omit it entirely, because --location/--port would
|
||||
# override anything --listen= might allocate). For now, just let it
|
||||
# pass, because that allows us to use --listen=tcp as the default in
|
||||
# optParameters, which (I think) gets included in the rendered --help
|
||||
# output, which is useful. In the future, let's reconsider the value
|
||||
# of that --help text (or achieve that documentation in some other
|
||||
# way), change the default to None, complain here if it's not None,
|
||||
# then change parseArgs() to transform the None into "tcp"
|
||||
else:
|
||||
# no --location and --port? expect --listen= (maybe the default), and --listen=tcp requires --hostname
|
||||
listeners = o['listen'].split(",")
|
||||
if 'tcp' in listeners and not o['hostname']:
|
||||
raise UsageError("--listen=tcp requires --hostname=")
|
||||
if 'tcp' not in listeners and o['hostname']:
|
||||
raise UsageError("--listen= must be tcp to use --hostname")
|
||||
for l in listeners:
|
||||
if l not in ["tcp", "tor", "i2p"]:
|
||||
raise UsageError("--listen= must be: tcp, tor, i2p")
|
||||
|
||||
class _CreateBaseOptions(BasedirOptions):
|
||||
optFlags = [
|
||||
("hide-ip", None, "prohibit any configuration that would reveal the node's IP address"),
|
||||
]
|
||||
|
||||
class CreateClientOptions(_CreateBaseOptions):
|
||||
synopsis = "[options] [NODEDIR]"
|
||||
description = "Create a client-only Tahoe-LAFS node (no storage server)."
|
||||
|
||||
optParameters = [
|
||||
# we provide 'create-node'-time options for the most common
|
||||
# configuration knobs. The rest can be controlled by editing
|
||||
@ -31,7 +72,6 @@ class _CreateBaseOptions(BasedirOptions):
|
||||
"Specify which TCP port to run the HTTP interface on. Use 'none' to disable."),
|
||||
("basedir", "C", None, "Specify which Tahoe base directory should be used. This has the same effect as the global --node-directory option. [default: %s]"
|
||||
% quote_local_unicode_path(_default_nodedir)),
|
||||
|
||||
]
|
||||
|
||||
# This is overridden in order to ensure we get a "Wrong number of
|
||||
@ -39,24 +79,43 @@ class _CreateBaseOptions(BasedirOptions):
|
||||
def parseArgs(self, basedir=None):
|
||||
BasedirOptions.parseArgs(self, basedir)
|
||||
|
||||
class CreateClientOptions(_CreateBaseOptions):
|
||||
synopsis = "[options] [NODEDIR]"
|
||||
description = "Create a client-only Tahoe-LAFS node (no storage server)."
|
||||
|
||||
class CreateNodeOptions(CreateClientOptions):
|
||||
optFlags = [
|
||||
("no-storage", None, "Do not offer storage service to other nodes."),
|
||||
]
|
||||
synopsis = "[options] [NODEDIR]"
|
||||
description = "Create a full Tahoe-LAFS node (client+server)."
|
||||
optParameters = WHERE_OPTS + [
|
||||
# we provide 'create-node'-time options for the most common
|
||||
# configuration knobs. The rest can be controlled by editing
|
||||
# tahoe.cfg before node startup.
|
||||
("hostname", None, None, "Specify the hostname for listening and advertising for this node."),
|
||||
("listen", None, "tcp", "Specify the listener type for this node."),
|
||||
("nickname", "n", None, "Specify the nickname for this node."),
|
||||
("introducer", "i", None, "Specify the introducer FURL to use."),
|
||||
("webport", "p", "tcp:3456:interface=127.0.0.1",
|
||||
"Specify which TCP port to run the HTTP interface on. Use 'none' to disable."),
|
||||
("basedir", "C", None, "Specify which Tahoe base directory should be used. This has the same effect as the global --node-directory option. [default: %s]"
|
||||
% quote_local_unicode_path(_default_nodedir)),
|
||||
|
||||
]
|
||||
|
||||
def parseArgs(self, basedir=None):
|
||||
CreateClientOptions.parseArgs(self, basedir)
|
||||
validate_where_options(self)
|
||||
|
||||
class CreateIntroducerOptions(NoDefaultBasedirOptions):
|
||||
subcommand_name = "create-introducer"
|
||||
description = "Create a Tahoe-LAFS introducer."
|
||||
optFlags = [
|
||||
("hide-ip", None, "prohibit any configuration that would reveal the node's IP address"),
|
||||
]
|
||||
|
||||
]
|
||||
optParameters = WHERE_OPTS + [("listen", None, "tcp", "Specify the listener type for this node."),
|
||||
("hostname", None, None, "Specify the hostname for listening and advertising for this node."),
|
||||
]
|
||||
def parseArgs(self, basedir=None):
|
||||
NoDefaultBasedirOptions.parseArgs(self, basedir)
|
||||
validate_where_options(self)
|
||||
|
||||
def write_node_config(c, config):
|
||||
# this is shared between clients and introducers
|
||||
@ -83,11 +142,29 @@ def write_node_config(c, config):
|
||||
webport = ""
|
||||
c.write("web.port = %s\n" % (webport.encode('utf-8'),))
|
||||
c.write("web.static = public_html\n")
|
||||
c.write("# to prevent the Tub from listening at all, use this:\n")
|
||||
c.write("# tub.port = disabled\n")
|
||||
c.write("# tub.location = disabled\n")
|
||||
c.write("#tub.port =\n")
|
||||
c.write("#tub.location = \n")
|
||||
|
||||
if 'hostname' in config and config['hostname'] is not None:
|
||||
new_port = iputil.allocate_tcp_port()
|
||||
c.write("tub.port = tcp:%s\n" % new_port)
|
||||
c.write("tub.location = tcp:%s:%s\n" % (config.get('hostname').encode('utf-8'), new_port))
|
||||
elif 'listen' in config and config['listen'] == "tor":
|
||||
raise NotImplementedError("This feature addition is being tracked by this ticket:" +
|
||||
"https://tahoe-lafs.org/trac/tahoe-lafs/ticket/2490")
|
||||
elif 'listen' in config and config['listen'] == "i2p":
|
||||
raise NotImplementedError("This feature addition is being tracked by this ticket:" +
|
||||
"https://tahoe-lafs.org/trac/tahoe-lafs/ticket/2490")
|
||||
elif config.get('port') is not None:
|
||||
c.write("tub.port = %s\n" % config.get('port').encode('utf-8'))
|
||||
c.write("tub.location = %s\n" % config.get('location').encode('utf-8'))
|
||||
else:
|
||||
c.write("tub.port = disabled\n")
|
||||
c.write("tub.location = disabled\n")
|
||||
|
||||
if config.get('hostname', None) or config.get('listen', None):
|
||||
c.write("# to prevent the Tub from listening at all, use this:\n")
|
||||
c.write("# tub.port = disabled\n")
|
||||
c.write("# tub.location = disabled\n")
|
||||
|
||||
c.write("#log_gatherer.furl =\n")
|
||||
c.write("#timeout.keepalive =\n")
|
||||
c.write("#timeout.disconnect =\n")
|
||||
|
@ -1,8 +1,9 @@
|
||||
import os
|
||||
from twisted.trial import unittest
|
||||
from twisted.internet import defer
|
||||
from twisted.python import usage
|
||||
from allmydata.util import configutil
|
||||
from ..common_util import run_cli
|
||||
from ..common_util import run_cli, parse_cli
|
||||
|
||||
class Config(unittest.TestCase):
|
||||
def read_config(self, basedir):
|
||||
@ -10,12 +11,34 @@ class Config(unittest.TestCase):
|
||||
config = configutil.get_config(tahoe_cfg)
|
||||
return config
|
||||
|
||||
def test_client_unrecognized_options(self):
|
||||
tests = [
|
||||
("--listen", "create-client", "--listen=tcp"),
|
||||
("--hostname", "create-client", "--hostname=computer"),
|
||||
("--port",
|
||||
"create-client", "--port=unix:/var/tahoe/socket",
|
||||
"--location=tor:myservice.onion:12345"),
|
||||
("--port", "create-client", "--port=unix:/var/tahoe/socket"),
|
||||
("--location",
|
||||
"create-client", "--location=tor:myservice.onion:12345"),
|
||||
("--listen", "create-client", "--listen=tor"),
|
||||
("--listen", "create-client", "--listen=i2p"),
|
||||
]
|
||||
for test in tests:
|
||||
option = test[0]
|
||||
verb = test[1]
|
||||
args = test[2:]
|
||||
e = self.assertRaises(usage.UsageError, parse_cli, verb, *args)
|
||||
self.assertIn("option %s not recognized" % (option,), str(e))
|
||||
|
||||
@defer.inlineCallbacks
|
||||
def test_client(self):
|
||||
basedir = self.mktemp()
|
||||
rc, out, err = yield run_cli("create-client", basedir)
|
||||
cfg = self.read_config(basedir)
|
||||
self.assertEqual(cfg.getboolean("node", "reveal-IP-address"), True)
|
||||
self.assertEqual(cfg.get("node", "tub.port"), "disabled")
|
||||
self.assertEqual(cfg.get("node", "tub.location"), "disabled")
|
||||
|
||||
@defer.inlineCallbacks
|
||||
def test_client_hide_ip(self):
|
||||
@ -27,27 +50,93 @@ class Config(unittest.TestCase):
|
||||
@defer.inlineCallbacks
|
||||
def test_node(self):
|
||||
basedir = self.mktemp()
|
||||
rc, out, err = yield run_cli("create-node", basedir)
|
||||
rc, out, err = yield run_cli("create-node", "--hostname=foo", basedir)
|
||||
cfg = self.read_config(basedir)
|
||||
self.assertEqual(cfg.getboolean("node", "reveal-IP-address"), True)
|
||||
|
||||
@defer.inlineCallbacks
|
||||
def test_node_hide_ip(self):
|
||||
basedir = self.mktemp()
|
||||
rc, out, err = yield run_cli("create-node", "--hide-ip", basedir)
|
||||
rc, out, err = yield run_cli("create-node", "--hide-ip",
|
||||
"--hostname=foo", basedir)
|
||||
cfg = self.read_config(basedir)
|
||||
self.assertEqual(cfg.getboolean("node", "reveal-IP-address"), False)
|
||||
|
||||
@defer.inlineCallbacks
|
||||
def test_introducer(self):
|
||||
def test_node_hostname(self):
|
||||
basedir = self.mktemp()
|
||||
rc, out, err = yield run_cli("create-introducer", basedir)
|
||||
rc, out, err = yield run_cli("create-node", "--hostname=computer", basedir)
|
||||
cfg = self.read_config(basedir)
|
||||
self.assertEqual(cfg.getboolean("node", "reveal-IP-address"), True)
|
||||
port = cfg.get("node", "tub.port")
|
||||
location = cfg.get("node", "tub.location")
|
||||
self.assertRegex(port, r'^tcp:\d+$')
|
||||
self.assertRegex(location, r'^tcp:computer:\d+$')
|
||||
|
||||
@defer.inlineCallbacks
|
||||
def test_node_port_location(self):
|
||||
basedir = self.mktemp()
|
||||
rc, out, err = yield run_cli("create-node",
|
||||
"--port=unix:/var/tahoe/socket",
|
||||
"--location=tor:myservice.onion:12345",
|
||||
basedir)
|
||||
cfg = self.read_config(basedir)
|
||||
self.assertEqual(cfg.get("node", "tub.location"), "tor:myservice.onion:12345")
|
||||
self.assertEqual(cfg.get("node", "tub.port"), "unix:/var/tahoe/socket")
|
||||
|
||||
def test_node_listen_tcp_no_hostname(self):
|
||||
basedir = self.mktemp()
|
||||
e = self.assertRaises(usage.UsageError,
|
||||
parse_cli,
|
||||
"create-node", "--listen=tcp", basedir)
|
||||
self.assertIn("--listen=tcp requires --hostname=", str(e))
|
||||
|
||||
@defer.inlineCallbacks
|
||||
def test_node_listen_tor(self):
|
||||
basedir = self.mktemp()
|
||||
d = run_cli("create-node", "--listen=tor", basedir)
|
||||
e = yield self.assertFailure(d, NotImplementedError)
|
||||
self.assertEqual(str(e), "This feature addition is being tracked by this ticket:" +
|
||||
"https://tahoe-lafs.org/trac/tahoe-lafs/ticket/2490")
|
||||
|
||||
@defer.inlineCallbacks
|
||||
def test_node_listen_i2p(self):
|
||||
basedir = self.mktemp()
|
||||
d = run_cli("create-node", "--listen=i2p", basedir)
|
||||
e = yield self.assertFailure(d, NotImplementedError)
|
||||
self.failUnlessEqual(str(e), "This feature addition is being tracked by this ticket:" +
|
||||
"https://tahoe-lafs.org/trac/tahoe-lafs/ticket/2490")
|
||||
|
||||
def test_node_port_only(self):
|
||||
e = self.assertRaises(usage.UsageError,
|
||||
parse_cli,
|
||||
"create-node", "--port=unix:/var/tahoe/socket")
|
||||
self.assertEqual(str(e), "--port must be used with --location")
|
||||
|
||||
def test_node_location_only(self):
|
||||
e = self.assertRaises(usage.UsageError,
|
||||
parse_cli,
|
||||
"create-node", "--location=tor:myservice.onion:12345")
|
||||
self.assertEqual(str(e), "--location must be used with --port")
|
||||
|
||||
def test_introducer_no_hostname(self):
|
||||
basedir = self.mktemp()
|
||||
e = self.assertRaises(usage.UsageError, parse_cli,
|
||||
"create-introducer", basedir)
|
||||
self.assertEqual(str(e), "--listen=tcp requires --hostname=")
|
||||
|
||||
@defer.inlineCallbacks
|
||||
def test_introducer_hide_ip(self):
|
||||
basedir = self.mktemp()
|
||||
rc, out, err = yield run_cli("create-introducer", "--hide-ip", basedir)
|
||||
rc, out, err = yield run_cli("create-introducer", "--hide-ip",
|
||||
"--hostname=foo", basedir)
|
||||
cfg = self.read_config(basedir)
|
||||
self.assertEqual(cfg.getboolean("node", "reveal-IP-address"), False)
|
||||
|
||||
@defer.inlineCallbacks
|
||||
def test_introducer_hostname(self):
|
||||
basedir = self.mktemp()
|
||||
rc, out, err = yield run_cli("create-introducer",
|
||||
"--hostname=foo", basedir)
|
||||
cfg = self.read_config(basedir)
|
||||
self.assertTrue("foo" in cfg.get("node", "tub.location"))
|
||||
self.assertEqual(cfg.getboolean("node", "reveal-IP-address"), True)
|
||||
|
@ -262,14 +262,14 @@ class CreateNode(unittest.TestCase):
|
||||
command)
|
||||
|
||||
def test_node(self):
|
||||
self.do_create("node")
|
||||
self.do_create("node", "--hostname=127.0.0.1")
|
||||
|
||||
def test_client(self):
|
||||
# create-client should behave like create-node --no-storage.
|
||||
self.do_create("client")
|
||||
|
||||
def test_introducer(self):
|
||||
self.do_create("introducer")
|
||||
self.do_create("introducer", "--hostname=127.0.0.1")
|
||||
|
||||
def test_stats_gatherer(self):
|
||||
self.do_create("stats-gatherer", "--hostname=127.0.0.1")
|
||||
@ -340,11 +340,10 @@ class RunNode(common_util.SignalMixin, unittest.TestCase, pollmixin.PollMixin,
|
||||
exit_trigger_file = os.path.join(c1, Client.EXIT_TRIGGER_FILE)
|
||||
twistd_pid_file = os.path.join(c1, "twistd.pid")
|
||||
introducer_furl_file = os.path.join(c1, "private", "introducer.furl")
|
||||
portnum_file = os.path.join(c1, "introducer.port")
|
||||
node_url_file = os.path.join(c1, "node.url")
|
||||
config_file = os.path.join(c1, "tahoe.cfg")
|
||||
|
||||
d = self.run_bintahoe(["--quiet", "create-introducer", "--basedir", c1])
|
||||
d = self.run_bintahoe(["--quiet", "create-introducer", "--basedir", c1, "--hostname", "localhost"])
|
||||
def _cb(res):
|
||||
out, err, rc_or_sig = res
|
||||
self.failUnlessEqual(rc_or_sig, 0)
|
||||
@ -390,11 +389,9 @@ class RunNode(common_util.SignalMixin, unittest.TestCase, pollmixin.PollMixin,
|
||||
d.addCallback(lambda res: self.poll(_node_has_started))
|
||||
|
||||
def _started(res):
|
||||
# read the introducer.furl and introducer.port files so we can
|
||||
# check that their contents don't change on restart
|
||||
# read the introducer.furl file so we can check that the contents
|
||||
# don't change on restart
|
||||
self.furl = fileutil.read(introducer_furl_file)
|
||||
self.failUnless(os.path.exists(portnum_file))
|
||||
self.portnum = fileutil.read(portnum_file)
|
||||
|
||||
fileutil.write(exit_trigger_file, "")
|
||||
self.failUnless(os.path.exists(twistd_pid_file))
|
||||
@ -418,14 +415,13 @@ class RunNode(common_util.SignalMixin, unittest.TestCase, pollmixin.PollMixin,
|
||||
# so poll until it is. This time introducer_furl_file already
|
||||
# exists, so we check for the existence of node_url_file instead.
|
||||
def _node_has_restarted():
|
||||
return os.path.exists(node_url_file) and os.path.exists(portnum_file)
|
||||
return os.path.exists(node_url_file)
|
||||
d.addCallback(lambda res: self.poll(_node_has_restarted))
|
||||
|
||||
def _check_same_furl_and_port(res):
|
||||
def _check_same_furl(res):
|
||||
self.failUnless(os.path.exists(introducer_furl_file))
|
||||
self.failUnlessEqual(self.furl, fileutil.read(introducer_furl_file))
|
||||
self.failUnlessEqual(self.portnum, fileutil.read(portnum_file))
|
||||
d.addCallback(_check_same_furl_and_port)
|
||||
d.addCallback(_check_same_furl)
|
||||
|
||||
# Now we can kill it. TODO: On a slow machine, the node might kill
|
||||
# itself before we get a chance to, especially if spawning the
|
||||
@ -463,7 +459,7 @@ class RunNode(common_util.SignalMixin, unittest.TestCase, pollmixin.PollMixin,
|
||||
c1 = os.path.join(basedir, "c1")
|
||||
exit_trigger_file = os.path.join(c1, Client.EXIT_TRIGGER_FILE)
|
||||
twistd_pid_file = os.path.join(c1, "twistd.pid")
|
||||
portnum_file = os.path.join(c1, "client.port")
|
||||
node_url_file = os.path.join(c1, "node.url")
|
||||
|
||||
d = self.run_bintahoe(["--quiet", "create-client", "--basedir", c1, "--webport", "0"])
|
||||
def _cb(res):
|
||||
@ -506,7 +502,7 @@ class RunNode(common_util.SignalMixin, unittest.TestCase, pollmixin.PollMixin,
|
||||
d.addCallback(_cb2)
|
||||
|
||||
def _node_has_started():
|
||||
return os.path.exists(portnum_file)
|
||||
return os.path.exists(node_url_file)
|
||||
d.addCallback(lambda res: self.poll(_node_has_started))
|
||||
|
||||
# now we can kill it. TODO: On a slow machine, the node might kill
|
||||
@ -527,11 +523,13 @@ class RunNode(common_util.SignalMixin, unittest.TestCase, pollmixin.PollMixin,
|
||||
c1 = os.path.join(basedir, "c1")
|
||||
exit_trigger_file = os.path.join(c1, Client.EXIT_TRIGGER_FILE)
|
||||
twistd_pid_file = os.path.join(c1, "twistd.pid")
|
||||
portnum_file = os.path.join(c1, "client.port")
|
||||
node_url_file = os.path.join(c1, "node.url")
|
||||
storage_furl_file = os.path.join(c1, "private", "storage.furl")
|
||||
config_file = os.path.join(c1, "tahoe.cfg")
|
||||
|
||||
d = self.run_bintahoe(["--quiet", "create-node", "--basedir", c1, "--webport", "0"])
|
||||
d = self.run_bintahoe(["--quiet", "create-node", "--basedir", c1,
|
||||
"--webport", "0",
|
||||
"--hostname", "localhost"])
|
||||
def _cb(res):
|
||||
out, err, rc_or_sig = res
|
||||
self.failUnlessEqual(rc_or_sig, 0)
|
||||
@ -540,9 +538,9 @@ class RunNode(common_util.SignalMixin, unittest.TestCase, pollmixin.PollMixin,
|
||||
config = fileutil.read(config_file)
|
||||
self.failUnlessIn('\nweb.port = 0\n', config)
|
||||
|
||||
# By writing this file, we get two minutes before the client will exit. This ensures
|
||||
# that even if the 'stop' command doesn't work (and the test fails), the client should
|
||||
# still terminate.
|
||||
# By writing this file, we get two minutes before the client will
|
||||
# exit. This ensures that even if the 'stop' command doesn't work
|
||||
# (and the test fails), the client should still terminate.
|
||||
fileutil.write(exit_trigger_file, "")
|
||||
# now it's safe to start the node
|
||||
d.addCallback(_cb)
|
||||
@ -570,14 +568,13 @@ class RunNode(common_util.SignalMixin, unittest.TestCase, pollmixin.PollMixin,
|
||||
d.addCallback(_cb2)
|
||||
|
||||
def _node_has_started():
|
||||
# this depends upon both files being created atomically
|
||||
return os.path.exists(node_url_file) and os.path.exists(portnum_file)
|
||||
return os.path.exists(node_url_file)
|
||||
d.addCallback(lambda res: self.poll(_node_has_started))
|
||||
|
||||
def _started(res):
|
||||
# read the client.port file so we can check that its contents
|
||||
# read the storage.furl file so we can check that its contents
|
||||
# don't change on restart
|
||||
self.portnum = fileutil.read(portnum_file)
|
||||
self.storage_furl = fileutil.read(storage_furl_file)
|
||||
|
||||
fileutil.write(exit_trigger_file, "")
|
||||
self.failUnless(os.path.exists(twistd_pid_file))
|
||||
@ -601,9 +598,10 @@ class RunNode(common_util.SignalMixin, unittest.TestCase, pollmixin.PollMixin,
|
||||
# so poll until it is
|
||||
d.addCallback(lambda res: self.poll(_node_has_started))
|
||||
|
||||
def _check_same_port(res):
|
||||
self.failUnlessEqual(self.portnum, fileutil.read(portnum_file))
|
||||
d.addCallback(_check_same_port)
|
||||
def _check_same_furl(res):
|
||||
self.failUnlessEqual(self.storage_furl,
|
||||
fileutil.read(storage_furl_file))
|
||||
d.addCallback(_check_same_furl)
|
||||
|
||||
# now we can kill it. TODO: On a slow machine, the node might kill
|
||||
# itself before we get a chance to, especially if spawning the
|
||||
|
Loading…
x
Reference in New Issue
Block a user