introduce create_node_dir

This commit is contained in:
meejah
2018-02-27 15:00:31 -07:00
parent c93ee4f867
commit d544284f92
6 changed files with 93 additions and 65 deletions

View File

@ -174,9 +174,10 @@ def create_client(basedir=u".", _client_factory=None):
:param _client_factory: for testing; the class to instantiate :param _client_factory: for testing; the class to instantiate
""" """
node.create_node_dir(basedir, CLIENT_README)
# load configuration # load configuration
config = read_config(basedir, u"client.port", _valid_config_sections=_valid_config_sections) config = read_config(basedir, u"client.port", _valid_config_sections=_valid_config_sections)
config.write_private_config("README", CLIENT_README)
if _client_factory is None: if _client_factory is None:
_client_factory = _Client _client_factory = _Client

View File

@ -29,14 +29,15 @@ class FurlFileConflictError(Exception):
#@defer.inlineCallbacks #@defer.inlineCallbacks
def create_introducer(basedir=u"."): def create_introducer(basedir=u"."):
from allmydata.node import read_config from allmydata import node
if not os.path.exists(basedir):
node.create_node_dir(basedir, INTRODUCER_README)
config = read_config( config = node.read_config(
basedir, u"client.port", basedir, u"client.port",
generated_files=["introducer.furl"], generated_files=["introducer.furl"],
_valid_config_sections=_valid_config_sections, _valid_config_sections=_valid_config_sections,
) )
config.write_private_config("README", INTRODUCER_README)
#defer.returnValue( #defer.returnValue(
return _IntroducerNode( return _IntroducerNode(
config, config,

View File

@ -127,6 +127,23 @@ class PrivacyError(Exception):
that the IP address could be revealed""" that the IP address could be revealed"""
def create_node_dir(basedir, readme_text):
"""
Create new new 'node directory' at 'basedir'. This includes a
'private' subdirectory. If basedir (and privdir) already exists,
nothing is done.
:param readme_text: text to put in <basedir>/private/README
"""
if not os.path.exists(basedir):
fileutil.make_dirs(basedir)
privdir = os.path.join(basedir, "private")
if not os.path.exists(privdir):
fileutil.make_dirs(privdir, 0700)
with open(os.path.join(privdir, 'README'), 'w') as f:
f.write(readme_text)
def read_config(basedir, portnumfile, generated_files=[], _valid_config_sections=None): def read_config(basedir, portnumfile, generated_files=[], _valid_config_sections=None):
basedir = abspath_expanduser_unicode(unicode(basedir)) basedir = abspath_expanduser_unicode(unicode(basedir))
if _valid_config_sections is None: if _valid_config_sections is None:
@ -305,7 +322,6 @@ class _Config(object):
config file that resides within the subdirectory named 'private'), and config file that resides within the subdirectory named 'private'), and
return it. return it.
""" """
fileutil.make_dirs(os.path.join(self._basedir, "private"), 0700)
privname = os.path.join(self._basedir, "private", name) privname = os.path.join(self._basedir, "private", name)
with open(privname, "w") as f: with open(privname, "w") as f:
f.write(value) f.write(value)

View File

@ -20,6 +20,7 @@ from allmydata.introducer.server import IntroducerService, FurlFileConflictError
from allmydata.introducer.common import get_tubid_string_from_ann, \ from allmydata.introducer.common import get_tubid_string_from_ann, \
get_tubid_string, sign_to_foolscap, unsign_from_foolscap, \ get_tubid_string, sign_to_foolscap, unsign_from_foolscap, \
UnknownKeyError UnknownKeyError
from allmydata.node import create_node_dir
# the "new way" to create introducer node instance # the "new way" to create introducer node instance
from allmydata.introducer.server import create_introducer from allmydata.introducer.server import create_introducer
from allmydata.web import introweb from allmydata.web import introweb
@ -42,7 +43,7 @@ class Node(testutil.SignalMixin, testutil.ReallyEqualMixin, unittest.TestCase):
def test_furl(self): def test_furl(self):
basedir = "introducer.IntroducerNode.test_furl" basedir = "introducer.IntroducerNode.test_furl"
os.mkdir(basedir) create_node_dir(basedir, "testing")
public_fn = os.path.join(basedir, "introducer.furl") public_fn = os.path.join(basedir, "introducer.furl")
private_fn = os.path.join(basedir, "private", "introducer.furl") private_fn = os.path.join(basedir, "private", "introducer.furl")
@ -75,7 +76,7 @@ class Node(testutil.SignalMixin, testutil.ReallyEqualMixin, unittest.TestCase):
def test_web_static(self): def test_web_static(self):
basedir = u"introducer.Node.test_web_static" basedir = u"introducer.Node.test_web_static"
os.mkdir(basedir) create_node_dir(basedir, "testing")
fileutil.write(os.path.join(basedir, "tahoe.cfg"), fileutil.write(os.path.join(basedir, "tahoe.cfg"),
"[node]\n" + "[node]\n" +
"web.port = tcp:0:interface=127.0.0.1\n" + "web.port = tcp:0:interface=127.0.0.1\n" +

View File

@ -14,7 +14,7 @@ from foolscap.api import flushEventualQueue
import foolscap.logging.log import foolscap.logging.log
from twisted.application import service from twisted.application import service
from allmydata.node import Node, formatTimeTahoeStyle, MissingConfigEntry, read_config, config_from_string from allmydata.node import Node, formatTimeTahoeStyle, MissingConfigEntry, read_config, config_from_string, create_node_dir
from allmydata.introducer.server import create_introducer from allmydata.introducer.server import create_introducer
from allmydata.client import create_client from allmydata.client import create_client
from allmydata.client import _valid_config_sections as client_valid_config_sections from allmydata.client import _valid_config_sections as client_valid_config_sections
@ -58,14 +58,13 @@ class TestCase(testutil.SignalMixin, unittest.TestCase):
return d return d
def _test_location(self, basedir, expected_addresses, tub_port=None, tub_location=None, local_addresses=None): def _test_location(self, basedir, expected_addresses, tub_port=None, tub_location=None, local_addresses=None):
fileutil.make_dirs(basedir) create_node_dir(basedir, "testing")
f = open(os.path.join(basedir, 'tahoe.cfg'), 'wt') with open(os.path.join(basedir, 'tahoe.cfg'), 'wt') as f:
f.write("[node]\n") f.write("[node]\n")
if tub_port: if tub_port:
f.write("tub.port = %d\n" % (tub_port,)) f.write("tub.port = %d\n" % (tub_port,))
if tub_location is not None: if tub_location is not None:
f.write("tub.location = %s\n" % (tub_location,)) f.write("tub.location = %s\n" % (tub_location,))
f.close()
if local_addresses: if local_addresses:
self.patch(iputil, 'get_local_addresses_sync', self.patch(iputil, 'get_local_addresses_sync',
@ -200,9 +199,7 @@ class TestCase(testutil.SignalMixin, unittest.TestCase):
def test_secrets_dir(self): def test_secrets_dir(self):
basedir = "test_node/test_secrets_dir" basedir = "test_node/test_secrets_dir"
fileutil.make_dirs(basedir) create_node_dir(basedir, "testing")
read_config(basedir, "")
self.failUnless(os.path.exists(os.path.join(basedir, "private"))) self.failUnless(os.path.exists(os.path.join(basedir, "private")))
def test_secrets_dir_protected(self): def test_secrets_dir_protected(self):
@ -212,9 +209,9 @@ class TestCase(testutil.SignalMixin, unittest.TestCase):
# that unprivileged users can't read this thing.) # that unprivileged users can't read this thing.)
raise unittest.SkipTest("We don't know how to set permissions on Windows.") raise unittest.SkipTest("We don't know how to set permissions on Windows.")
basedir = "test_node/test_secrets_dir_protected" basedir = "test_node/test_secrets_dir_protected"
fileutil.make_dirs(basedir) create_node_dir(basedir, "nothing to see here")
read_config(basedir, "")
# make sure private dir was created with correct modes
privdir = os.path.join(basedir, "private") privdir = os.path.join(basedir, "private")
st = os.stat(privdir) st = os.stat(privdir)
bits = stat.S_IMODE(st[stat.ST_MODE]) bits = stat.S_IMODE(st[stat.ST_MODE])
@ -222,7 +219,6 @@ class TestCase(testutil.SignalMixin, unittest.TestCase):
def test_logdir_is_str(self): def test_logdir_is_str(self):
basedir = "test_node/test_logdir_is_str" basedir = "test_node/test_logdir_is_str"
fileutil.make_dirs(basedir)
ns = Namespace() ns = Namespace()
ns.called = False ns.called = False
@ -231,14 +227,18 @@ class TestCase(testutil.SignalMixin, unittest.TestCase):
self.failUnless(isinstance(logdir, str), logdir) self.failUnless(isinstance(logdir, str), logdir)
self.patch(foolscap.logging.log, 'setLogDir', call_setLogDir) self.patch(foolscap.logging.log, 'setLogDir', call_setLogDir)
create_node_dir(basedir, "nothing to see here")
TestNode(basedir) TestNode(basedir)
self.failUnless(ns.called) self.failUnless(ns.called)
class EmptyNode(Node): class EmptyNode(Node):
def __init__(self): def __init__(self, config=None):
if config is None:
config = config_from_string("", "no portfile", 'no basedir') config = config_from_string("", "no portfile", 'no basedir')
Node.__init__(self, config) Node.__init__(self, config)
EXPECTED = { EXPECTED = {
# top-level key is tub.port category # top-level key is tub.port category
"missing": { "missing": {
@ -288,14 +288,14 @@ class PortLocation(unittest.TestCase):
"hintstring": "tcp:HOST:888,AUTO", "hintstring": "tcp:HOST:888,AUTO",
}[tl] }[tl]
n = EmptyNode()
basedir = os.path.join("test_node/portlocation/%s/%s" % (tp, tl)) basedir = os.path.join("test_node/portlocation/%s/%s" % (tp, tl))
fileutil.make_dirs(basedir) create_node_dir(basedir, "testing")
config = n.config = read_config( config = read_config(
basedir, basedir,
"node.port", "node.port",
_valid_config_sections=_valid_config_sections, _valid_config_sections=client_valid_config_sections,
) )
n = EmptyNode(config)
n._reveal_ip = True n._reveal_ip = True
if exp in ("ERR1", "ERR2", "ERR3", "ERR4"): if exp in ("ERR1", "ERR2", "ERR3", "ERR4"):
@ -394,27 +394,27 @@ class FakeTub:
class Listeners(unittest.TestCase): class Listeners(unittest.TestCase):
def test_multiple_ports(self): def test_multiple_ports(self):
n = EmptyNode() basedir = self.mktemp()
n.basedir = self.mktemp() create_node_dir(basedir, "testing")
n.config_fname = os.path.join(n.basedir, "tahoe.cfg")
os.mkdir(n.basedir)
os.mkdir(os.path.join(n.basedir, "private"))
port1 = iputil.allocate_tcp_port() port1 = iputil.allocate_tcp_port()
port2 = iputil.allocate_tcp_port() port2 = iputil.allocate_tcp_port()
port = ("tcp:%d:interface=127.0.0.1,tcp:%d:interface=127.0.0.1" % port = ("tcp:%d:interface=127.0.0.1,tcp:%d:interface=127.0.0.1" %
(port1, port2)) (port1, port2))
location = "tcp:localhost:%d,tcp:localhost:%d" % (port1, port2) location = "tcp:localhost:%d,tcp:localhost:%d" % (port1, port2)
with open(n.config_fname, "w") as f: with open(os.path.join(basedir, "tahoe.cfg"), "w") as f:
f.write(BASE_CONFIG) f.write(BASE_CONFIG)
f.write("tub.port = %s\n" % port) f.write("tub.port = %s\n" % port)
f.write("tub.location = %s\n" % location) f.write("tub.location = %s\n" % location)
# we're doing a lot of calling-into-setup-methods here, it might be # we're doing a lot of calling-into-setup-methods here, it might be
# better to just create a real Node instance, I'm not sure. # better to just create a real Node instance, I'm not sure.
n.config = read_config( config = read_config(
n.basedir, basedir,
"client.port", "client.port",
_valid_config_sections=client_valid_config_sections, _valid_config_sections=client_valid_config_sections,
) )
n = EmptyNode(config)
n.check_privacy() n.check_privacy()
n.services = [] n.services = []
n.create_i2p_provider() n.create_i2p_provider()
@ -429,43 +429,49 @@ class Listeners(unittest.TestCase):
"tcp:%d:interface=127.0.0.1" % port2]) "tcp:%d:interface=127.0.0.1" % port2])
def test_tor_i2p_listeners(self): def test_tor_i2p_listeners(self):
n = EmptyNode() basedir = self.mktemp()
n.basedir = self.mktemp() config_fname = os.path.join(basedir, "tahoe.cfg")
n.config_fname = os.path.join(n.basedir, "tahoe.cfg") os.mkdir(basedir)
os.mkdir(n.basedir) os.mkdir(os.path.join(basedir, "private"))
os.mkdir(os.path.join(n.basedir, "private")) with open(config_fname, "w") as f:
with open(n.config_fname, "w") as f:
f.write(BASE_CONFIG) f.write(BASE_CONFIG)
f.write("tub.port = listen:i2p,listen:tor\n") f.write("tub.port = listen:i2p,listen:tor\n")
f.write("tub.location = tcp:example.org:1234\n") f.write("tub.location = tcp:example.org:1234\n")
# we're doing a lot of calling-into-setup-methods here, it might be # we're doing a lot of calling-into-setup-methods here, it might be
# better to just create a real Node instance, I'm not sure. # better to just create a real Node instance, I'm not sure.
n.config = read_config( config = read_config(
n.basedir, n.basedir,
"client.port", "client.port",
_valid_config_sections=client_valid_config_sections, _valid_config_sections=client_valid_config_sections,
) )
n.check_privacy()
n.services = []
i2p_ep = object() i2p_ep = object()
i2p_prov = i2p_provider.Provider(config, mock.Mock())
i2p_prov.get_listener = mock.Mock(return_value=i2p_ep)
i2p_x = mock.Mock()
i2p_x.Provider = lambda c, r: i2p_prov
i2p_mock = mock.patch('allmydata.node.i2p_provider', new=i2p_x)
tor_ep = object() tor_ep = object()
n._i2p_provider = mock.Mock() tor_prov = tor_provider.Provider(config, mock.Mock())
n._i2p_provider.get_listener = mock.Mock(return_value=i2p_ep) tor_prov.get_listener = mock.Mock(return_value=tor_ep)
n._tor_provider = mock.Mock() tor_x = mock.Mock()
n._tor_provider.get_listener = mock.Mock(return_value=tor_ep) tor_x.Provider = lambda c, r: tor_prov
n.init_connections() tor_mock = mock.patch('allmydata.node.tor_provider', new=tor_x)
n.set_tub_options()
t = FakeTub() tub_mock = mock.patch("allmydata.node.Tub", return_value=FakeTub())
with mock.patch("allmydata.node.Tub", return_value=t): with i2p_mock, tor_mock, tub_mock:
n.create_main_tub() n = EmptyNode(config)
self.assertEqual(n._i2p_provider.get_listener.mock_calls, [mock.call()]) self.assertEqual(n._i2p_provider.get_listener.mock_calls, [mock.call()])
self.assertEqual(n._tor_provider.get_listener.mock_calls, [mock.call()]) self.assertEqual(n._tor_provider.get_listener.mock_calls, [mock.call()])
self.assertEqual(t.listening_ports, [i2p_ep, tor_ep]) self.assertIn(i2p_ep, n.tub.listening_ports)
self.assertIn(tor_ep, n.tub.listening_ports)
class ClientNotListening(unittest.TestCase): class ClientNotListening(unittest.TestCase):
def test_disabled(self): def test_disabled(self):
basedir = "test_node/test_disabled" basedir = "test_node/test_disabled"
fileutil.make_dirs(basedir) create_node_dir(basedir, "testing")
f = open(os.path.join(basedir, 'tahoe.cfg'), 'wt') f = open(os.path.join(basedir, 'tahoe.cfg'), 'wt')
f.write(BASE_CONFIG) f.write(BASE_CONFIG)
f.write(NOLISTEN) f.write(NOLISTEN)
@ -476,7 +482,7 @@ class ClientNotListening(unittest.TestCase):
def test_disabled_but_storage(self): def test_disabled_but_storage(self):
basedir = "test_node/test_disabled_but_storage" basedir = "test_node/test_disabled_but_storage"
fileutil.make_dirs(basedir) create_node_dir(basedir, "testing")
f = open(os.path.join(basedir, 'tahoe.cfg'), 'wt') f = open(os.path.join(basedir, 'tahoe.cfg'), 'wt')
f.write(BASE_CONFIG) f.write(BASE_CONFIG)
f.write(NOLISTEN) f.write(NOLISTEN)
@ -487,7 +493,7 @@ class ClientNotListening(unittest.TestCase):
def test_disabled_but_helper(self): def test_disabled_but_helper(self):
basedir = "test_node/test_disabled_but_helper" basedir = "test_node/test_disabled_but_helper"
fileutil.make_dirs(basedir) create_node_dir(basedir, "testing")
f = open(os.path.join(basedir, 'tahoe.cfg'), 'wt') f = open(os.path.join(basedir, 'tahoe.cfg'), 'wt')
f.write(BASE_CONFIG) f.write(BASE_CONFIG)
f.write(NOLISTEN) f.write(NOLISTEN)
@ -500,12 +506,11 @@ class ClientNotListening(unittest.TestCase):
class IntroducerNotListening(unittest.TestCase): class IntroducerNotListening(unittest.TestCase):
def test_port_none_introducer(self): def test_port_none_introducer(self):
basedir = "test_node/test_port_none_introducer" basedir = "test_node/test_port_none_introducer"
fileutil.make_dirs(basedir) create_node_dir(basedir, "testing")
f = open(os.path.join(basedir, 'tahoe.cfg'), 'wt') with open(os.path.join(basedir, 'tahoe.cfg'), 'wt') as f:
f.write("[node]\n") f.write("[node]\n")
f.write("tub.port = disabled\n") f.write("tub.port = disabled\n")
f.write("tub.location = disabled\n") f.write("tub.location = disabled\n")
f.close()
e = self.assertRaises(ValueError, create_introducer, basedir) e = self.assertRaises(ValueError, create_introducer, basedir)
self.assertIn("we are Introducer, but tub is not listening", str(e)) self.assertIn("we are Introducer, but tub is not listening", str(e))

View File

@ -2,6 +2,7 @@ from twisted.trial import unittest
from foolscap.api import fireEventually, flushEventualQueue from foolscap.api import fireEventually, flushEventualQueue
from twisted.internet import defer from twisted.internet import defer
from allmydata.introducer import IntroducerNode from allmydata.introducer import IntroducerNode
from allmydata import node
from .common import FAVICON_MARKUP from .common import FAVICON_MARKUP
from ..common_web import do_http from ..common_web import do_http
@ -23,9 +24,12 @@ class IntroducerWeb(unittest.TestCase):
"tub.location = 127.0.0.1:1\n" "tub.location = 127.0.0.1:1\n"
"web.port = tcp:0\n" "web.port = tcp:0\n"
) )
basedir = self.mktemp()
node.create_node_dir(basedir, "testing")
from allmydata.node import config_from_string from allmydata.node import config_from_string
self.node = IntroducerNode( self.node = IntroducerNode(
config_from_string(config, "introducer.port", "no-basedir"), config_from_string(config, "introducer.port", basedir),
) )
self.ws = self.node.getServiceNamed("webish") self.ws = self.node.getServiceNamed("webish")