Pull "config" handling out of Node and hide node-derivitives

This includes:

 - refactor to create_client and _Client
 - refactor to _IntroducerNode and create_introducer
This commit is contained in:
meejah 2017-09-05 19:08:35 -06:00
parent 7e5a87e800
commit 1b6f477549
18 changed files with 297 additions and 199 deletions

View File

@ -17,7 +17,7 @@ from allmydata.immutable.offloaded import Helper
from allmydata.control import ControlServer from allmydata.control import ControlServer
from allmydata.introducer.client import IntroducerClient from allmydata.introducer.client import IntroducerClient
from allmydata.util import (hashutil, base32, pollmixin, log, keyutil, idlib, from allmydata.util import (hashutil, base32, pollmixin, log, keyutil, idlib,
yamlutil, configutil) yamlutil)
from allmydata.util.encodingutil import (get_filesystem_encoding, from allmydata.util.encodingutil import (get_filesystem_encoding,
from_utf8_or_none) from_utf8_or_none)
from allmydata.util.fileutil import abspath_expanduser_unicode from allmydata.util.fileutil import abspath_expanduser_unicode
@ -153,10 +153,22 @@ class Terminator(service.Service):
return service.Service.stopService(self) return service.Service.stopService(self)
@implementer(IStatsProducer) #@defer.inlineCallbacks
class Client(node.Node, pollmixin.PollMixin): def create_client(basedir=u"."):
from allmydata.node import read_config
config = read_config(basedir, u"client.port")
config.validate(_valid_config_sections())
#defer.returnValue(
return _Client(
config,
basedir=basedir
)
#)
@implementer(IStatsProducer)
class _Client(node.Node, pollmixin.PollMixin):
PORTNUMFILE = "client.port"
STOREDIR = 'storage' STOREDIR = 'storage'
NODETYPE = "client" NODETYPE = "client"
EXIT_TRIGGER_FILE = "exit_trigger" EXIT_TRIGGER_FILE = "exit_trigger"
@ -176,12 +188,10 @@ class Client(node.Node, pollmixin.PollMixin):
"max_segment_size": 128*KiB, "max_segment_size": 128*KiB,
} }
def __init__(self, basedir="."): def __init__(self, config, basedir=u"."):
node.Node.__init__(self, basedir) node.Node.__init__(self, config, basedir=basedir)
# All tub.registerReference must happen *after* we upcall, since # All tub.registerReference must happen *after* we upcall, since
# that's what does tub.setLocation() # that's what does tub.setLocation()
configutil.validate_config(self.config_fname, self.config,
_valid_config_sections())
self._magic_folder = None self._magic_folder = None
self.started_timestamp = time.time() self.started_timestamp = time.time()
self.logSource="Client" self.logSource="Client"

View File

@ -2,7 +2,7 @@
# This is for compatibilty with old .tac files, which reference # This is for compatibilty with old .tac files, which reference
# allmydata.introducer.IntroducerNode # allmydata.introducer.IntroducerNode
from allmydata.introducer.server import IntroducerNode from allmydata.introducer.server import _IntroducerNode as IntroducerNode
# hush pyflakes # hush pyflakes
_unused = [IntroducerNode] _unused = [IntroducerNode]

View File

@ -5,7 +5,7 @@ from twisted.application import service
from foolscap.api import Referenceable from foolscap.api import Referenceable
import allmydata import allmydata
from allmydata import node from allmydata import node
from allmydata.util import log, rrefutil, configutil from allmydata.util import log, rrefutil
from allmydata.util.fileutil import abspath_expanduser_unicode from allmydata.util.fileutil import abspath_expanduser_unicode
from allmydata.introducer.interfaces import \ from allmydata.introducer.interfaces import \
RIIntroducerPublisherAndSubscriberService_v2 RIIntroducerPublisherAndSubscriberService_v2
@ -19,14 +19,24 @@ def _valid_config_sections():
class FurlFileConflictError(Exception): class FurlFileConflictError(Exception):
pass pass
class IntroducerNode(node.Node): #@defer.inlineCallbacks
PORTNUMFILE = "introducer.port" def create_introducer(basedir=u"."):
NODETYPE = "introducer" from allmydata.node import read_config
GENERATED_FILES = ['introducer.furl'] config = read_config(basedir, u"client.port", generated_files=["introducer.furl"])
config.validate(_valid_config_sections())
#defer.returnValue(
return _IntroducerNode(
config,
basedir=basedir
)
#)
def __init__(self, basedir=u"."):
node.Node.__init__(self, basedir) class _IntroducerNode(node.Node):
configutil.validate_config(self.config_fname, self.config, _valid_config_sections()) NODETYPE = "introducer"
def __init__(self, config, basedir=u"."):
node.Node.__init__(self, config, basedir=basedir)
self.init_introducer() self.init_introducer()
webport = self.get_config("node", "web.port", None) webport = self.get_config("node", "web.port", None)
if webport: if webport:

View File

@ -1,4 +1,5 @@
import datetime, os.path, re, types, ConfigParser, tempfile import datetime, os.path, re, types, ConfigParser, tempfile
from io import BytesIO
from base64 import b32decode, b32encode from base64 import b32decode, b32encode
from twisted.internet import reactor from twisted.internet import reactor
@ -106,28 +107,144 @@ class PrivacyError(Exception):
"""reveal-IP-address = false, but the node is configured in such a way """reveal-IP-address = false, but the node is configured in such a way
that the IP address could be revealed""" that the IP address could be revealed"""
def read_config(basedir, portnumfile, generated_files=[], _valid_config_sections=None):
basedir = abspath_expanduser_unicode(unicode(basedir))
if _valid_config_sections is None:
_valid_config_sections = _common_config_sections
# complain if there's bad stuff in the config dir
_error_about_old_config_files(basedir, generated_files)
# canonicalize the portnum file
portnumfile = os.path.join(basedir, portnumfile)
# (try to) read the main config file
config_fname = os.path.join(basedir, "tahoe.cfg")
parser = ConfigParser.SafeConfigParser()
try:
parser = configutil.get_config(config_fname)
except EnvironmentError:
if os.path.exists(config_fname):
raise
configutil.validate_config(config_fname, parser, _valid_config_sections())
return _Config(parser, portnumfile, config_fname)
def config_from_string(config_str, portnumfile):
parser = ConfigParser.SafeConfigParser()
parser.readfp(BytesIO(config_str))
return _Config(parser, portnumfile, '<in-memory>')
def _error_about_old_config_files(basedir, generated_files):
"""
If any old configuration files are detected, raise
OldConfigError.
"""
oldfnames = set()
old_names = [
'nickname', 'webport', 'keepalive_timeout', 'log_gatherer.furl',
'disconnect_timeout', 'advertised_ip_addresses', 'introducer.furl',
'helper.furl', 'key_generator.furl', 'stats_gatherer.furl',
'no_storage', 'readonly_storage', 'sizelimit',
'debug_discard_storage', 'run_helper'
]
for fn in generated_files:
old_names.remove(fn)
for name in old_names:
fullfname = os.path.join(basedir, name)
if os.path.exists(fullfname):
oldfnames.add(fullfname)
if oldfnames:
e = OldConfigError(oldfnames)
twlog.msg(e)
raise e
class _Config(object):
"""
FIXME better name
pulling out all the 'config' stuff from Node, so we can pass it in
as a helper instead.
"""
def __init__(self, configparser, portnum_fname, config_fname):
# XXX I think this portnumfile thing is just legacy?
self.portnum_fname = portnum_fname
self._config_fname = config_fname
self.config = configparser
nickname_utf8 = self.get_config("node", "nickname", "<unspecified>")
self.nickname = nickname_utf8.decode("utf-8")
assert type(self.nickname) is unicode
def validate(self, valid_config_sections):
configutil.validate_config(self._config_fname, self.config, valid_config_sections)
def read_config(self):
try:
self.config = configutil.get_config(self.config_fname)
except EnvironmentError:
if os.path.exists(self.config_fname):
raise
def get_config(self, section, option, default=_None, boolean=False):
try:
if boolean:
return self.config.getboolean(section, option)
item = self.config.get(section, option)
if option.endswith(".furl") and self._contains_unescaped_hash(item):
raise UnescapedHashError(section, option, item)
return item
except (ConfigParser.NoOptionError, ConfigParser.NoSectionError):
if default is _None:
raise MissingConfigEntry(
"{} is missing the [{}]{} entry".format(
quote_output(self._config_fname),
section,
option,
)
)
return default
@staticmethod
def _contains_unescaped_hash(item):
characters = iter(item)
for c in characters:
if c == '\\':
characters.next()
elif c == '#':
return True
return False
class Node(service.MultiService): class Node(service.MultiService):
# this implements common functionality of both Client nodes and Introducer # this implements common functionality of both Client nodes and Introducer
# nodes. # nodes.
NODETYPE = "unknown NODETYPE" NODETYPE = "unknown NODETYPE"
PORTNUMFILE = None
CERTFILE = "node.pem" CERTFILE = "node.pem"
GENERATED_FILES = [] GENERATED_FILES = []
def __init__(self, basedir=u"."): def __init__(self, config, basedir=u"."):
service.MultiService.__init__(self) service.MultiService.__init__(self)
# ideally, this would only be in _Config (or otherwise abstracted)
self.basedir = abspath_expanduser_unicode(unicode(basedir)) self.basedir = abspath_expanduser_unicode(unicode(basedir))
self.config_fname = os.path.join(self.basedir, "tahoe.cfg") # XXX don't write files in ctor!
self._portnumfile = os.path.join(self.basedir, self.PORTNUMFILE)
fileutil.make_dirs(os.path.join(self.basedir, "private"), 0700) fileutil.make_dirs(os.path.join(self.basedir, "private"), 0700)
with open(os.path.join(self.basedir, "private", "README"), "w") as f: with open(os.path.join(self.basedir, "private", "README"), "w") as f:
f.write(PRIV_README) f.write(PRIV_README)
# creates self.config self.config = config
self.read_config() self.get_config = config.get_config # XXX stopgap
nickname_utf8 = self.get_config("node", "nickname", "<unspecified>") self.nickname = config.nickname # XXX stopgap
self.nickname = nickname_utf8.decode("utf-8")
assert type(self.nickname) is unicode
self.init_tempdir() self.init_tempdir()
self.check_privacy() self.check_privacy()
@ -147,7 +264,7 @@ class Node(service.MultiService):
iputil.increase_rlimits() iputil.increase_rlimits()
def init_tempdir(self): def init_tempdir(self):
tempdir_config = self.get_config("node", "tempdir", "tmp").decode('utf-8') tempdir_config = self.config.get_config("node", "tempdir", "tmp").decode('utf-8')
tempdir = abspath_expanduser_unicode(tempdir_config, base=self.basedir) tempdir = abspath_expanduser_unicode(tempdir_config, base=self.basedir)
if not os.path.exists(tempdir): if not os.path.exists(tempdir):
fileutil.make_dirs(tempdir) fileutil.make_dirs(tempdir)
@ -159,73 +276,16 @@ class Node(service.MultiService):
test_name = tempfile.mktemp() test_name = tempfile.mktemp()
_assert(os.path.dirname(test_name) == tempdir, test_name, tempdir) _assert(os.path.dirname(test_name) == tempdir, test_name, tempdir)
@staticmethod
def _contains_unescaped_hash(item):
characters = iter(item)
for c in characters:
if c == '\\':
characters.next()
elif c == '#':
return True
return False
def get_config(self, section, option, default=_None, boolean=False):
try:
if boolean:
return self.config.getboolean(section, option)
item = self.config.get(section, option)
if option.endswith(".furl") and self._contains_unescaped_hash(item):
raise UnescapedHashError(section, option, item)
return item
except (ConfigParser.NoOptionError, ConfigParser.NoSectionError):
if default is _None:
fn = os.path.join(self.basedir, u"tahoe.cfg")
raise MissingConfigEntry("%s is missing the [%s]%s entry"
% (quote_output(fn), section, option))
return default
def read_config(self):
self.error_about_old_config_files()
self.config = ConfigParser.SafeConfigParser()
try:
self.config = configutil.get_config(self.config_fname)
except EnvironmentError:
if os.path.exists(self.config_fname):
raise
def error_about_old_config_files(self):
""" If any old configuration files are detected, raise OldConfigError. """
oldfnames = set()
for name in [
'nickname', 'webport', 'keepalive_timeout', 'log_gatherer.furl',
'disconnect_timeout', 'advertised_ip_addresses', 'introducer.furl',
'helper.furl', 'key_generator.furl', 'stats_gatherer.furl',
'no_storage', 'readonly_storage', 'sizelimit',
'debug_discard_storage', 'run_helper']:
if name not in self.GENERATED_FILES:
fullfname = os.path.join(self.basedir, name)
if os.path.exists(fullfname):
oldfnames.add(fullfname)
if oldfnames:
e = OldConfigError(oldfnames)
twlog.msg(e)
raise e
def check_privacy(self): def check_privacy(self):
self._reveal_ip = self.get_config("node", "reveal-IP-address", True, self._reveal_ip = self.config.get_config("node", "reveal-IP-address", True,
boolean=True) boolean=True)
def create_i2p_provider(self): def create_i2p_provider(self):
self._i2p_provider = i2p_provider.Provider(self.basedir, self, reactor) self._i2p_provider = i2p_provider.Provider(self.basedir, self.config, reactor)
self._i2p_provider.check_dest_config() self._i2p_provider.check_dest_config()
self._i2p_provider.setServiceParent(self) self._i2p_provider.setServiceParent(self)
def create_tor_provider(self): def create_tor_provider(self):
self._tor_provider = tor_provider.Provider(self.basedir, self, reactor) self._tor_provider = tor_provider.Provider(self.basedir, self.config, reactor)
self._tor_provider.check_onion_config() self._tor_provider.check_onion_config()
self._tor_provider.setServiceParent(self) self._tor_provider.setServiceParent(self)
@ -254,7 +314,7 @@ class Node(service.MultiService):
# then we remember the default mappings from tahoe.cfg # then we remember the default mappings from tahoe.cfg
self._default_connection_handlers = {"tor": "tor", "i2p": "i2p"} self._default_connection_handlers = {"tor": "tor", "i2p": "i2p"}
tcp_handler_name = self.get_config("connections", "tcp", "tcp").lower() tcp_handler_name = self.config.get_config("connections", "tcp", "tcp").lower()
if tcp_handler_name == "disabled": if tcp_handler_name == "disabled":
self._default_connection_handlers["tcp"] = None self._default_connection_handlers["tcp"] = None
else: else:
@ -282,10 +342,10 @@ class Node(service.MultiService):
} }
# see #521 for a discussion of how to pick these timeout values. # see #521 for a discussion of how to pick these timeout values.
keepalive_timeout_s = self.get_config("node", "timeout.keepalive", "") keepalive_timeout_s = self.config.get_config("node", "timeout.keepalive", "")
if keepalive_timeout_s: if keepalive_timeout_s:
self.tub_options["keepaliveTimeout"] = int(keepalive_timeout_s) self.tub_options["keepaliveTimeout"] = int(keepalive_timeout_s)
disconnect_timeout_s = self.get_config("node", "timeout.disconnect", "") disconnect_timeout_s = self.config.get_config("node", "timeout.disconnect", "")
if disconnect_timeout_s: if disconnect_timeout_s:
# N.B.: this is in seconds, so use "1800" to get 30min # N.B.: this is in seconds, so use "1800" to get 30min
self.tub_options["disconnectTimeout"] = int(disconnect_timeout_s) self.tub_options["disconnectTimeout"] = int(disconnect_timeout_s)
@ -340,12 +400,12 @@ class Node(service.MultiService):
# For 'tub.port', tahoe.cfg overrides the individual file on # For 'tub.port', tahoe.cfg overrides the individual file on
# disk. So only read self._portnumfile if tahoe.cfg doesn't # disk. So only read self._portnumfile if tahoe.cfg doesn't
# provide a value. # provide a value.
if os.path.exists(self._portnumfile): if os.path.exists(self.config.portnum_fname):
file_tubport = fileutil.read(self._portnumfile).strip() file_tubport = fileutil.read(self.config.portnum_fname).strip()
tubport = self._convert_tub_port(file_tubport) tubport = self._convert_tub_port(file_tubport)
else: else:
tubport = "tcp:%d" % iputil.allocate_tcp_port() tubport = "tcp:%d" % iputil.allocate_tcp_port()
fileutil.write_atomically(self._portnumfile, tubport + "\n", fileutil.write_atomically(self.config.portnum_fname, tubport + "\n",
mode="") mode="")
else: else:
tubport = self._convert_tub_port(cfg_tubport) tubport = self._convert_tub_port(cfg_tubport)
@ -392,8 +452,8 @@ class Node(service.MultiService):
self.nodeid = b32decode(self.tub.tubID.upper()) # binary format self.nodeid = b32decode(self.tub.tubID.upper()) # binary format
self.write_config("my_nodeid", b32encode(self.nodeid).lower() + "\n") self.write_config("my_nodeid", b32encode(self.nodeid).lower() + "\n")
self.short_nodeid = b32encode(self.nodeid).lower()[:8] # for printing self.short_nodeid = b32encode(self.nodeid).lower()[:8] # for printing
cfg_tubport = self.get_config("node", "tub.port", None) cfg_tubport = self.config.get_config("node", "tub.port", None)
cfg_location = self.get_config("node", "tub.location", None) cfg_location = self.config.get_config("node", "tub.location", None)
portlocation = self.get_tub_portlocation(cfg_tubport, cfg_location) portlocation = self.get_tub_portlocation(cfg_tubport, cfg_location)
if portlocation: if portlocation:
tubport, location = portlocation tubport, location = portlocation
@ -573,7 +633,7 @@ class Node(service.MultiService):
if os.path.exists(lgfurl_file): if os.path.exists(lgfurl_file):
os.remove(lgfurl_file) os.remove(lgfurl_file)
self.log_tub.setOption("logport-furlfile", lgfurl_file) self.log_tub.setOption("logport-furlfile", lgfurl_file)
lgfurl = self.get_config("node", "log_gatherer.furl", "") lgfurl = self.config.get_config("node", "log_gatherer.furl", "")
if lgfurl: if lgfurl:
# this is in addition to the contents of log-gatherer-furlfile # this is in addition to the contents of log-gatherer-furlfile
self.log_tub.setOption("log-gatherer-furl", lgfurl) self.log_tub.setOption("log-gatherer-furl", lgfurl)

View File

@ -6,6 +6,7 @@ from twisted.python import usage
from twisted.python.reflect import namedAny from twisted.python.reflect import namedAny
from allmydata.scripts.default_nodedir import _default_nodedir from allmydata.scripts.default_nodedir import _default_nodedir
from allmydata.util import fileutil from allmydata.util import fileutil
from allmydata.node import read_config
from allmydata.util.encodingutil import listdir_unicode, quote_local_unicode_path from allmydata.util.encodingutil import listdir_unicode, quote_local_unicode_path
from twisted.application.service import Service from twisted.application.service import Service
@ -113,9 +114,9 @@ class DaemonizeTheRealService(Service):
def start(): def start():
node_to_instance = { node_to_instance = {
u"client": lambda: namedAny("allmydata.client.Client")(self.basedir), u"client": lambda: namedAny("allmydata.client.create_client")(self.basedir),
u"introducer": lambda: namedAny("allmydata.introducer.server.IntroducerNode")(self.basedir), u"introducer": lambda: namedAny("allmydata.introducer.server.create_introducer")(self.basedir),
u"stats-gatherer": lambda: namedAny("allmydata.stats.StatsGathererService")(self.basedir, verbose=True), u"stats-gatherer": lambda: namedAny("allmydata.stats.StatsGathererService")(read_config(self.basedir, None), self.basedir, verbose=True),
u"key-generator": key_generator_removed, u"key-generator": key_generator_removed,
} }

View File

@ -26,7 +26,7 @@ import treq
from allmydata.util.assertutil import _assert from allmydata.util.assertutil import _assert
from allmydata import uri as tahoe_uri from allmydata import uri as tahoe_uri
from allmydata.client import Client from allmydata.client import _Client
from allmydata.storage.server import StorageServer, storage_index_to_dir from allmydata.storage.server import StorageServer, storage_index_to_dir
from allmydata.util import fileutil, idlib, hashutil from allmydata.util import fileutil, idlib, hashutil
from allmydata.util.hashutil import permute_server_hash from allmydata.util.hashutil import permute_server_hash
@ -183,7 +183,16 @@ class NoNetworkStorageBroker(object):
def get_known_servers(self): def get_known_servers(self):
return [] # FIXME? return [] # FIXME?
class NoNetworkClient(Client):
def NoNetworkClient(basedir):
# XXX FIXME this is just to avoid massive search-replace for now;
# should be create_nonetwork_client() or something...
from allmydata.node import read_config
config = read_config(basedir, u'client.port')
return _NoNetworkClient(config, basedir=basedir)
class _NoNetworkClient(_Client):
def init_connections(self): def init_connections(self):
pass pass

View File

@ -7,7 +7,7 @@ import allmydata
import allmydata.frontends.magic_folder import allmydata.frontends.magic_folder
import allmydata.util.log import allmydata.util.log
from allmydata.node import Node, OldConfigError, OldConfigOptionError, MissingConfigEntry, UnescapedHashError from allmydata.node import OldConfigError, OldConfigOptionError, MissingConfigEntry, UnescapedHashError, _Config, read_config
from allmydata.frontends.auth import NeedRootcapLookupScheme from allmydata.frontends.auth import NeedRootcapLookupScheme
from allmydata import client from allmydata import client
from allmydata.storage_client import StorageFarmBroker from allmydata.storage_client import StorageFarmBroker
@ -32,7 +32,7 @@ class Basic(testutil.ReallyEqualMixin, testutil.NonASCIIPathMixin, unittest.Test
os.mkdir(basedir) os.mkdir(basedir)
fileutil.write(os.path.join(basedir, "tahoe.cfg"), \ fileutil.write(os.path.join(basedir, "tahoe.cfg"), \
BASECONFIG) BASECONFIG)
client.Client(basedir) client.create_client(basedir)
def test_comment(self): def test_comment(self):
should_fail = [r"test#test", r"#testtest", r"test\\#test"] should_fail = [r"test#test", r"#testtest", r"test\\#test"]
@ -47,15 +47,15 @@ class Basic(testutil.ReallyEqualMixin, testutil.NonASCIIPathMixin, unittest.Test
fileutil.write(os.path.join(basedir, "tahoe.cfg"), config) fileutil.write(os.path.join(basedir, "tahoe.cfg"), config)
for s in should_fail: for s in should_fail:
self.failUnless(Node._contains_unescaped_hash(s)) self.failUnless(_Config._contains_unescaped_hash(s))
write_config(s) write_config(s)
e = self.assertRaises(UnescapedHashError, client.Client, basedir) e = self.assertRaises(UnescapedHashError, client.create_client, basedir)
self.assertIn("[client]introducer.furl", str(e)) self.assertIn("[client]introducer.furl", str(e))
for s in should_not_fail: for s in should_not_fail:
self.failIf(Node._contains_unescaped_hash(s)) self.failIf(_Config._contains_unescaped_hash(s))
write_config(s) write_config(s)
client.Client(basedir) client.create_client(basedir)
def test_unreadable_config(self): def test_unreadable_config(self):
if sys.platform == "win32": if sys.platform == "win32":
@ -70,7 +70,7 @@ class Basic(testutil.ReallyEqualMixin, testutil.NonASCIIPathMixin, unittest.Test
old_mode = os.stat(fn).st_mode old_mode = os.stat(fn).st_mode
os.chmod(fn, 0) os.chmod(fn, 0)
try: try:
e = self.assertRaises(EnvironmentError, client.Client, basedir) e = self.assertRaises(EnvironmentError, read_config, basedir, "client.port")
self.assertIn("Permission denied", str(e)) self.assertIn("Permission denied", str(e))
finally: finally:
# don't leave undeleteable junk lying around # don't leave undeleteable junk lying around
@ -92,7 +92,7 @@ class Basic(testutil.ReallyEqualMixin, testutil.NonASCIIPathMixin, unittest.Test
logged_messages = [] logged_messages = []
self.patch(twisted.python.log, 'msg', logged_messages.append) self.patch(twisted.python.log, 'msg', logged_messages.append)
e = self.failUnlessRaises(OldConfigError, client.Client, basedir) e = self.failUnlessRaises(OldConfigError, read_config, basedir, "client.port")
abs_basedir = fileutil.abspath_expanduser_unicode(unicode(basedir)).encode(sys.getfilesystemencoding()) abs_basedir = fileutil.abspath_expanduser_unicode(unicode(basedir)).encode(sys.getfilesystemencoding())
self.failUnlessIn(os.path.join(abs_basedir, "introducer.furl"), e.args[0]) self.failUnlessIn(os.path.join(abs_basedir, "introducer.furl"), e.args[0])
self.failUnlessIn(os.path.join(abs_basedir, "no_storage"), e.args[0]) self.failUnlessIn(os.path.join(abs_basedir, "no_storage"), e.args[0])
@ -119,7 +119,7 @@ class Basic(testutil.ReallyEqualMixin, testutil.NonASCIIPathMixin, unittest.Test
os.mkdir(basedir) os.mkdir(basedir)
fileutil.write(os.path.join(basedir, "tahoe.cfg"), \ fileutil.write(os.path.join(basedir, "tahoe.cfg"), \
BASECONFIG) BASECONFIG)
c = client.Client(basedir) c = client.create_client(basedir)
secret_fname = os.path.join(basedir, "private", "secret") secret_fname = os.path.join(basedir, "private", "secret")
self.failUnless(os.path.exists(secret_fname), secret_fname) self.failUnless(os.path.exists(secret_fname), secret_fname)
renew_secret = c.get_renewal_secret() renew_secret = c.get_renewal_secret()
@ -132,7 +132,7 @@ class Basic(testutil.ReallyEqualMixin, testutil.NonASCIIPathMixin, unittest.Test
os.mkdir(basedir) os.mkdir(basedir)
fileutil.write(os.path.join(basedir, "tahoe.cfg"), fileutil.write(os.path.join(basedir, "tahoe.cfg"),
BASECONFIG) BASECONFIG)
c = client.Client(basedir) c = client.create_client(basedir)
self.failUnless(c.get_long_nodeid().startswith("v0-")) self.failUnless(c.get_long_nodeid().startswith("v0-"))
def test_nodekey_no_storage(self): def test_nodekey_no_storage(self):
@ -140,7 +140,7 @@ class Basic(testutil.ReallyEqualMixin, testutil.NonASCIIPathMixin, unittest.Test
os.mkdir(basedir) os.mkdir(basedir)
fileutil.write(os.path.join(basedir, "tahoe.cfg"), fileutil.write(os.path.join(basedir, "tahoe.cfg"),
BASECONFIG + "[storage]\n" + "enabled = false\n") BASECONFIG + "[storage]\n" + "enabled = false\n")
c = client.Client(basedir) c = client.create_client(basedir)
self.failUnless(c.get_long_nodeid().startswith("v0-")) self.failUnless(c.get_long_nodeid().startswith("v0-"))
def test_reserved_1(self): def test_reserved_1(self):
@ -151,7 +151,7 @@ class Basic(testutil.ReallyEqualMixin, testutil.NonASCIIPathMixin, unittest.Test
"[storage]\n" + \ "[storage]\n" + \
"enabled = true\n" + \ "enabled = true\n" + \
"reserved_space = 1000\n") "reserved_space = 1000\n")
c = client.Client(basedir) c = client.create_client(basedir)
self.failUnlessEqual(c.getServiceNamed("storage").reserved_space, 1000) self.failUnlessEqual(c.getServiceNamed("storage").reserved_space, 1000)
def test_reserved_2(self): def test_reserved_2(self):
@ -162,7 +162,7 @@ class Basic(testutil.ReallyEqualMixin, testutil.NonASCIIPathMixin, unittest.Test
"[storage]\n" + \ "[storage]\n" + \
"enabled = true\n" + \ "enabled = true\n" + \
"reserved_space = 10K\n") "reserved_space = 10K\n")
c = client.Client(basedir) c = client.create_client(basedir)
self.failUnlessEqual(c.getServiceNamed("storage").reserved_space, 10*1000) self.failUnlessEqual(c.getServiceNamed("storage").reserved_space, 10*1000)
def test_reserved_3(self): def test_reserved_3(self):
@ -173,7 +173,7 @@ class Basic(testutil.ReallyEqualMixin, testutil.NonASCIIPathMixin, unittest.Test
"[storage]\n" + \ "[storage]\n" + \
"enabled = true\n" + \ "enabled = true\n" + \
"reserved_space = 5mB\n") "reserved_space = 5mB\n")
c = client.Client(basedir) c = client.create_client(basedir)
self.failUnlessEqual(c.getServiceNamed("storage").reserved_space, self.failUnlessEqual(c.getServiceNamed("storage").reserved_space,
5*1000*1000) 5*1000*1000)
@ -185,7 +185,7 @@ class Basic(testutil.ReallyEqualMixin, testutil.NonASCIIPathMixin, unittest.Test
"[storage]\n" + \ "[storage]\n" + \
"enabled = true\n" + \ "enabled = true\n" + \
"reserved_space = 78Gb\n") "reserved_space = 78Gb\n")
c = client.Client(basedir) c = client.create_client(basedir)
self.failUnlessEqual(c.getServiceNamed("storage").reserved_space, self.failUnlessEqual(c.getServiceNamed("storage").reserved_space,
78*1000*1000*1000) 78*1000*1000*1000)
@ -197,7 +197,7 @@ class Basic(testutil.ReallyEqualMixin, testutil.NonASCIIPathMixin, unittest.Test
"[storage]\n" + \ "[storage]\n" + \
"enabled = true\n" + \ "enabled = true\n" + \
"reserved_space = bogus\n") "reserved_space = bogus\n")
self.failUnlessRaises(ValueError, client.Client, basedir) self.failUnlessRaises(ValueError, client.create_client, basedir)
def test_web_staticdir(self): def test_web_staticdir(self):
basedir = u"client.Basic.test_web_staticdir" basedir = u"client.Basic.test_web_staticdir"
@ -207,7 +207,7 @@ class Basic(testutil.ReallyEqualMixin, testutil.NonASCIIPathMixin, unittest.Test
"[node]\n" + "[node]\n" +
"web.port = tcp:0:interface=127.0.0.1\n" + "web.port = tcp:0:interface=127.0.0.1\n" +
"web.static = relative\n") "web.static = relative\n")
c = client.Client(basedir) c = client.create_client(basedir)
w = c.getServiceNamed("webish") w = c.getServiceNamed("webish")
abs_basedir = fileutil.abspath_expanduser_unicode(basedir) abs_basedir = fileutil.abspath_expanduser_unicode(basedir)
expected = fileutil.abspath_expanduser_unicode(u"relative", abs_basedir) expected = fileutil.abspath_expanduser_unicode(u"relative", abs_basedir)
@ -226,7 +226,7 @@ class Basic(testutil.ReallyEqualMixin, testutil.NonASCIIPathMixin, unittest.Test
"accounts.file = private/accounts\n")) "accounts.file = private/accounts\n"))
os.mkdir(os.path.join(basedir, "private")) os.mkdir(os.path.join(basedir, "private"))
fileutil.write(os.path.join(basedir, "private", "accounts"), "\n") fileutil.write(os.path.join(basedir, "private", "accounts"), "\n")
c = client.Client(basedir) # just make sure it can be instantiated c = client.create_client(basedir) # just make sure it can be instantiated
del c del c
def test_ftp_auth_url(self): def test_ftp_auth_url(self):
@ -238,7 +238,7 @@ class Basic(testutil.ReallyEqualMixin, testutil.NonASCIIPathMixin, unittest.Test
"enabled = true\n" "enabled = true\n"
"port = tcp:0:interface=127.0.0.1\n" "port = tcp:0:interface=127.0.0.1\n"
"accounts.url = http://0.0.0.0/\n")) "accounts.url = http://0.0.0.0/\n"))
c = client.Client(basedir) # just make sure it can be instantiated c = client.create_client(basedir) # just make sure it can be instantiated
del c del c
def test_ftp_auth_no_accountfile_or_url(self): def test_ftp_auth_no_accountfile_or_url(self):
@ -249,7 +249,7 @@ class Basic(testutil.ReallyEqualMixin, testutil.NonASCIIPathMixin, unittest.Test
"[ftpd]\n" "[ftpd]\n"
"enabled = true\n" "enabled = true\n"
"port = tcp:0:interface=127.0.0.1\n")) "port = tcp:0:interface=127.0.0.1\n"))
self.failUnlessRaises(NeedRootcapLookupScheme, client.Client, basedir) self.failUnlessRaises(NeedRootcapLookupScheme, client.create_client, basedir)
def _permute(self, sb, key): def _permute(self, sb, key):
return [ s.get_longname() for s in sb.get_servers_for_psi(key) ] return [ s.get_longname() for s in sb.get_servers_for_psi(key) ]
@ -285,7 +285,7 @@ class Basic(testutil.ReallyEqualMixin, testutil.NonASCIIPathMixin, unittest.Test
BASECONFIG + \ BASECONFIG + \
"[storage]\n" + \ "[storage]\n" + \
"enabled = true\n") "enabled = true\n")
c = client.Client(basedir) c = client.create_client(basedir)
ss = c.getServiceNamed("storage") ss = c.getServiceNamed("storage")
verdict = ss.remote_get_version() verdict = ss.remote_get_version()
self.failUnlessReallyEqual(verdict["application-version"], self.failUnlessReallyEqual(verdict["application-version"],
@ -307,7 +307,7 @@ class Basic(testutil.ReallyEqualMixin, testutil.NonASCIIPathMixin, unittest.Test
def _check(config, expected_furl): def _check(config, expected_furl):
fileutil.write(os.path.join(basedir, "tahoe.cfg"), fileutil.write(os.path.join(basedir, "tahoe.cfg"),
BASECONFIG + config) BASECONFIG + config)
c = client.Client(basedir) c = client.create_client(basedir)
uploader = c.getServiceNamed("uploader") uploader = c.getServiceNamed("uploader")
furl, connected = uploader.get_helper_info() furl, connected = uploader.get_helper_info()
self.failUnlessEqual(furl, expected_furl) self.failUnlessEqual(furl, expected_furl)
@ -352,20 +352,20 @@ class Basic(testutil.ReallyEqualMixin, testutil.NonASCIIPathMixin, unittest.Test
fileutil.write(os.path.join(basedir1, "tahoe.cfg"), fileutil.write(os.path.join(basedir1, "tahoe.cfg"),
config + "local.directory = " + local_dir_utf8 + "\n") config + "local.directory = " + local_dir_utf8 + "\n")
self.failUnlessRaises(MissingConfigEntry, client.Client, basedir1) self.failUnlessRaises(MissingConfigEntry, client.create_client, basedir1)
fileutil.write(os.path.join(basedir1, "tahoe.cfg"), config) fileutil.write(os.path.join(basedir1, "tahoe.cfg"), config)
fileutil.write(os.path.join(basedir1, "private", "magic_folder_dircap"), "URI:DIR2:blah") fileutil.write(os.path.join(basedir1, "private", "magic_folder_dircap"), "URI:DIR2:blah")
fileutil.write(os.path.join(basedir1, "private", "collective_dircap"), "URI:DIR2:meow") fileutil.write(os.path.join(basedir1, "private", "collective_dircap"), "URI:DIR2:meow")
self.failUnlessRaises(MissingConfigEntry, client.Client, basedir1) self.failUnlessRaises(MissingConfigEntry, client.create_client, basedir1)
fileutil.write(os.path.join(basedir1, "tahoe.cfg"), fileutil.write(os.path.join(basedir1, "tahoe.cfg"),
config.replace("[magic_folder]\n", "[drop_upload]\n")) config.replace("[magic_folder]\n", "[drop_upload]\n"))
self.failUnlessRaises(OldConfigOptionError, client.Client, basedir1) self.failUnlessRaises(OldConfigOptionError, client.create_client, basedir1)
fileutil.write(os.path.join(basedir1, "tahoe.cfg"), fileutil.write(os.path.join(basedir1, "tahoe.cfg"),
config + "local.directory = " + local_dir_utf8 + "\n") config + "local.directory = " + local_dir_utf8 + "\n")
c1 = client.Client(basedir1) c1 = client.create_client(basedir1)
magicfolder = c1.getServiceNamed('magic-folder') magicfolder = c1.getServiceNamed('magic-folder')
self.failUnless(isinstance(magicfolder, MockMagicFolder), magicfolder) self.failUnless(isinstance(magicfolder, MockMagicFolder), magicfolder)
self.failUnlessReallyEqual(magicfolder.client, c1) self.failUnlessReallyEqual(magicfolder.client, c1)
@ -391,7 +391,7 @@ class Basic(testutil.ReallyEqualMixin, testutil.NonASCIIPathMixin, unittest.Test
"local.directory = " + local_dir_utf8 + "\n") "local.directory = " + local_dir_utf8 + "\n")
fileutil.write(os.path.join(basedir2, "private", "magic_folder_dircap"), "URI:DIR2:blah") fileutil.write(os.path.join(basedir2, "private", "magic_folder_dircap"), "URI:DIR2:blah")
fileutil.write(os.path.join(basedir2, "private", "collective_dircap"), "URI:DIR2:meow") fileutil.write(os.path.join(basedir2, "private", "collective_dircap"), "URI:DIR2:meow")
self.failUnlessRaises(Boom, client.Client, basedir2) self.failUnlessRaises(Boom, client.create_client, basedir2)
def flush_but_dont_ignore(res): def flush_but_dont_ignore(res):
@ -416,15 +416,15 @@ class Run(unittest.TestCase, testutil.StallMixin):
os.mkdir(basedir) os.mkdir(basedir)
dummy = "pb://wl74cyahejagspqgy4x5ukrvfnevlknt@127.0.0.1:58889/bogus" dummy = "pb://wl74cyahejagspqgy4x5ukrvfnevlknt@127.0.0.1:58889/bogus"
fileutil.write(os.path.join(basedir, "tahoe.cfg"), BASECONFIG_I % dummy) fileutil.write(os.path.join(basedir, "tahoe.cfg"), BASECONFIG_I % dummy)
fileutil.write(os.path.join(basedir, client.Client.EXIT_TRIGGER_FILE), "") fileutil.write(os.path.join(basedir, client._Client.EXIT_TRIGGER_FILE), "")
client.Client(basedir) client.create_client(basedir)
def test_reloadable(self): def test_reloadable(self):
basedir = "test_client.Run.test_reloadable" basedir = "test_client.Run.test_reloadable"
os.mkdir(basedir) os.mkdir(basedir)
dummy = "pb://wl74cyahejagspqgy4x5ukrvfnevlknt@127.0.0.1:58889/bogus" dummy = "pb://wl74cyahejagspqgy4x5ukrvfnevlknt@127.0.0.1:58889/bogus"
fileutil.write(os.path.join(basedir, "tahoe.cfg"), BASECONFIG_I % dummy) fileutil.write(os.path.join(basedir, "tahoe.cfg"), BASECONFIG_I % dummy)
c1 = client.Client(basedir) c1 = client.create_client(basedir)
c1.setServiceParent(self.sparent) c1.setServiceParent(self.sparent)
# delay to let the service start up completely. I'm not entirely sure # delay to let the service start up completely. I'm not entirely sure
@ -446,7 +446,7 @@ class Run(unittest.TestCase, testutil.StallMixin):
# also change _check_exit_trigger to use it instead of a raw # also change _check_exit_trigger to use it instead of a raw
# reactor.stop, also instrument the shutdown event in an # reactor.stop, also instrument the shutdown event in an
# attribute that we can check.) # attribute that we can check.)
c2 = client.Client(basedir) c2 = client.create_client(basedir)
c2.setServiceParent(self.sparent) c2.setServiceParent(self.sparent)
return c2.disownServiceParent() return c2.disownServiceParent()
d.addCallback(_restart) d.addCallback(_restart)
@ -457,7 +457,7 @@ class NodeMaker(testutil.ReallyEqualMixin, unittest.TestCase):
basedir = "client/NodeMaker/maker" basedir = "client/NodeMaker/maker"
fileutil.make_dirs(basedir) fileutil.make_dirs(basedir)
fileutil.write(os.path.join(basedir, "tahoe.cfg"), BASECONFIG) fileutil.write(os.path.join(basedir, "tahoe.cfg"), BASECONFIG)
c = client.Client(basedir) c = client.create_client(basedir)
n = c.create_node_from_uri("URI:CHK:6nmrpsubgbe57udnexlkiwzmlu:bjt7j6hshrlmadjyr7otq3dc24end5meo5xcr5xe5r663po6itmq:3:10:7277") n = c.create_node_from_uri("URI:CHK:6nmrpsubgbe57udnexlkiwzmlu:bjt7j6hshrlmadjyr7otq3dc24end5meo5xcr5xe5r663po6itmq:3:10:7277")
self.failUnless(IFilesystemNode.providedBy(n)) self.failUnless(IFilesystemNode.providedBy(n))

View File

@ -1,20 +1,18 @@
import os import os
import mock import mock
from io import BytesIO
from twisted.trial import unittest from twisted.trial import unittest
from twisted.internet import reactor, endpoints, defer from twisted.internet import reactor, endpoints, defer
from twisted.internet.interfaces import IStreamClientEndpoint from twisted.internet.interfaces import IStreamClientEndpoint
from ConfigParser import SafeConfigParser
from foolscap.connections import tcp from foolscap.connections import tcp
from ..node import Node, PrivacyError from ..node import Node, PrivacyError
from ..util import connection_status from ..util import connection_status
class FakeNode(Node): class FakeNode(Node):
def __init__(self, config_str): def __init__(self, config_str):
self.config = SafeConfigParser() from allmydata.node import config_from_string
self.config.readfp(BytesIO(config_str)) self.config = config_from_string(config_str, "fake.port")
self._reveal_ip = True
self.basedir = "BASEDIR" self.basedir = "BASEDIR"
self._reveal_ip = True
self.services = [] self.services = []
self.create_i2p_provider() self.create_i2p_provider()
self.create_tor_provider() self.create_tor_provider()

View File

@ -7,7 +7,7 @@ from twisted.trial import unittest
from twisted.internet import defer from twisted.internet import defer
from twisted.internet.interfaces import IConsumer from twisted.internet.interfaces import IConsumer
from allmydata import uri, dirnode from allmydata import uri, dirnode
from allmydata.client import Client from allmydata.client import _Client
from allmydata.immutable import upload from allmydata.immutable import upload
from allmydata.interfaces import IImmutableFileNode, IMutableFileNode, \ from allmydata.interfaces import IImmutableFileNode, IMutableFileNode, \
ExistingChildError, NoSuchChildError, MustNotBeUnknownRWError, \ ExistingChildError, NoSuchChildError, MustNotBeUnknownRWError, \
@ -1553,7 +1553,7 @@ class FakeNodeMaker(NodeMaker):
def create_mutable_file(self, contents="", keysize=None, version=None): def create_mutable_file(self, contents="", keysize=None, version=None):
return defer.succeed(FakeMutableFile(contents)) return defer.succeed(FakeMutableFile(contents))
class FakeClient2(Client): class FakeClient2(_Client):
def __init__(self): def __init__(self):
self.nodemaker = FakeNodeMaker(None, None, None, self.nodemaker = FakeNodeMaker(None, None, None,
None, None, None, None,

View File

@ -16,10 +16,10 @@ 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
# test compatibility with old introducer .tac files # the "new way" to create introducer node instance
from allmydata.introducer import IntroducerNode from allmydata.introducer.server import create_introducer
from allmydata.web import introweb from allmydata.web import introweb
from allmydata.client import Client as TahoeClient from allmydata.client import create_client
from allmydata.util import pollmixin, keyutil, idlib, fileutil, iputil, yamlutil from allmydata.util import pollmixin, keyutil, idlib, fileutil, iputil, yamlutil
import allmydata.test.common_util as testutil import allmydata.test.common_util as testutil
@ -28,13 +28,19 @@ class LoggingMultiService(service.MultiService):
log.msg(msg, **kw) log.msg(msg, **kw)
class Node(testutil.SignalMixin, testutil.ReallyEqualMixin, unittest.TestCase): class Node(testutil.SignalMixin, testutil.ReallyEqualMixin, unittest.TestCase):
def test_backwards_compat_import(self):
# for old introducer .tac files
from allmydata.introducer import IntroducerNode
IntroducerNode # pyflakes
def test_furl(self): def test_furl(self):
basedir = "introducer.IntroducerNode.test_furl" basedir = "introducer.IntroducerNode.test_furl"
os.mkdir(basedir) os.mkdir(basedir)
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")
q1 = IntroducerNode(basedir) q1 = create_introducer(basedir)
del q1 del q1
# new nodes create unguessable furls in private/introducer.furl # new nodes create unguessable furls in private/introducer.furl
ifurl = fileutil.read(private_fn) ifurl = fileutil.read(private_fn)
@ -48,13 +54,13 @@ class Node(testutil.SignalMixin, testutil.ReallyEqualMixin, unittest.TestCase):
# if we see both files, throw an error # if we see both files, throw an error
self.failUnlessRaises(FurlFileConflictError, self.failUnlessRaises(FurlFileConflictError,
IntroducerNode, basedir) create_introducer, basedir)
# when we see only the public one, move it to private/ and use # when we see only the public one, move it to private/ and use
# the existing furl instead of creating a new one # the existing furl instead of creating a new one
os.unlink(private_fn) os.unlink(private_fn)
q2 = IntroducerNode(basedir) q2 = create_introducer(basedir)
del q2 del q2
self.failIf(os.path.exists(public_fn)) self.failIf(os.path.exists(public_fn))
ifurl2 = fileutil.read(private_fn) ifurl2 = fileutil.read(private_fn)
@ -68,7 +74,7 @@ class Node(testutil.SignalMixin, testutil.ReallyEqualMixin, unittest.TestCase):
"[node]\n" + "[node]\n" +
"web.port = tcp:0:interface=127.0.0.1\n" + "web.port = tcp:0:interface=127.0.0.1\n" +
"web.static = relative\n") "web.static = relative\n")
c = IntroducerNode(basedir) c = create_introducer(basedir)
w = c.getServiceNamed("webish") w = c.getServiceNamed("webish")
abs_basedir = fileutil.abspath_expanduser_unicode(basedir) abs_basedir = fileutil.abspath_expanduser_unicode(basedir)
expected = fileutil.abspath_expanduser_unicode(u"relative", abs_basedir) expected = fileutil.abspath_expanduser_unicode(u"relative", abs_basedir)
@ -740,7 +746,7 @@ class Announcements(unittest.TestCase):
f.write("enabled = false\n") f.write("enabled = false\n")
f.close() f.close()
c = TahoeClient(basedir) c = create_client(basedir)
ic = c.introducer_clients[0] ic = c.introducer_clients[0]
sk_s, vk_s = keyutil.make_keypair() sk_s, vk_s = keyutil.make_keypair()
sk, _ignored = keyutil.parse_privkey(sk_s) sk, _ignored = keyutil.parse_privkey(sk_s)
@ -808,7 +814,7 @@ class Announcements(unittest.TestCase):
self.failUnlessEqual(announcements[pub2]["anonymous-storage-FURL"], self.failUnlessEqual(announcements[pub2]["anonymous-storage-FURL"],
furl3) furl3)
c2 = TahoeClient(basedir) c2 = create_client(basedir)
c2.introducer_clients[0]._load_announcements() c2.introducer_clients[0]._load_announcements()
yield flushEventualQueue() yield flushEventualQueue()
self.assertEqual(c2.storage_broker.get_all_serverids(), self.assertEqual(c2.storage_broker.get_all_serverids(),
@ -829,7 +835,7 @@ class ClientSeqnums(unittest.TestCase):
f.write("enabled = false\n") f.write("enabled = false\n")
f.close() f.close()
c = TahoeClient(basedir) c = create_client(basedir)
ic = c.introducer_clients[0] ic = c.introducer_clients[0]
outbound = ic._outbound_announcements outbound = ic._outbound_announcements
published = ic._published_announcements published = ic._published_announcements

View File

@ -4,7 +4,7 @@ import os
from twisted.python.filepath import FilePath from twisted.python.filepath import FilePath
from twisted.trial import unittest from twisted.trial import unittest
from allmydata.util import yamlutil from allmydata.util import yamlutil
from allmydata.client import Client from allmydata.client import create_client
from allmydata.scripts.create_node import write_node_config from allmydata.scripts.create_node import write_node_config
INTRODUCERS_CFG_FURLS=['furl1', 'furl2'] INTRODUCERS_CFG_FURLS=['furl1', 'furl2']
@ -44,7 +44,7 @@ class MultiIntroTests(unittest.TestCase):
} }
self.yaml_path.setContent(yamlutil.safe_dump(connections)) self.yaml_path.setContent(yamlutil.safe_dump(connections))
# get a client and count of introducer_clients # get a client and count of introducer_clients
myclient = Client(self.basedir) myclient = create_client(self.basedir)
ic_count = len(myclient.introducer_clients) ic_count = len(myclient.introducer_clients)
# assertions # assertions
@ -56,7 +56,7 @@ class MultiIntroTests(unittest.TestCase):
commented.""" commented."""
self.yaml_path.setContent(INTRODUCERS_CFG_FURLS_COMMENTED) self.yaml_path.setContent(INTRODUCERS_CFG_FURLS_COMMENTED)
# get a client and count of introducer_clients # get a client and count of introducer_clients
myclient = Client(self.basedir) myclient = create_client(self.basedir)
ic_count = len(myclient.introducer_clients) ic_count = len(myclient.introducer_clients)
# assertions # assertions
@ -78,7 +78,7 @@ class MultiIntroTests(unittest.TestCase):
c.close() c.close()
# get a client and first introducer_furl # get a client and first introducer_furl
myclient = Client(self.basedir) myclient = create_client(self.basedir)
tahoe_cfg_furl = myclient.introducer_furls[0] tahoe_cfg_furl = myclient.introducer_furls[0]
# assertions # assertions
@ -89,7 +89,7 @@ class MultiIntroTests(unittest.TestCase):
u'default': { 'furl': 'furl1' }, u'default': { 'furl': 'furl1' },
}} }}
self.yaml_path.setContent(yamlutil.safe_dump(connections)) self.yaml_path.setContent(yamlutil.safe_dump(connections))
e = self.assertRaises(ValueError, Client, self.basedir) e = self.assertRaises(ValueError, create_client, self.basedir)
self.assertEquals(str(e), "'default' introducer furl cannot be specified in introducers.yaml; please fix impossible configuration.") self.assertEquals(str(e), "'default' introducer furl cannot be specified in introducers.yaml; please fix impossible configuration.")
SIMPLE_YAML = """ SIMPLE_YAML = """
@ -129,25 +129,25 @@ class NoDefault(unittest.TestCase):
u'one': { 'furl': 'furl1' }, u'one': { 'furl': 'furl1' },
}} }}
self.yaml_path.setContent(yamlutil.safe_dump(connections)) self.yaml_path.setContent(yamlutil.safe_dump(connections))
myclient = Client(self.basedir) myclient = create_client(self.basedir)
tahoe_cfg_furl = myclient.introducer_furls[0] tahoe_cfg_furl = myclient.introducer_furls[0]
self.assertEquals(tahoe_cfg_furl, 'furl1') self.assertEquals(tahoe_cfg_furl, 'furl1')
def test_real_yaml(self): def test_real_yaml(self):
self.yaml_path.setContent(SIMPLE_YAML) self.yaml_path.setContent(SIMPLE_YAML)
myclient = Client(self.basedir) myclient = create_client(self.basedir)
tahoe_cfg_furl = myclient.introducer_furls[0] tahoe_cfg_furl = myclient.introducer_furls[0]
self.assertEquals(tahoe_cfg_furl, 'furl1') self.assertEquals(tahoe_cfg_furl, 'furl1')
def test_invalid_equals_yaml(self): def test_invalid_equals_yaml(self):
self.yaml_path.setContent(EQUALS_YAML) self.yaml_path.setContent(EQUALS_YAML)
e = self.assertRaises(TypeError, Client, self.basedir) e = self.assertRaises(TypeError, create_client, self.basedir)
self.assertEquals(str(e), "string indices must be integers") self.assertEquals(str(e), "string indices must be integers")
def test_introducerless(self): def test_introducerless(self):
connections = {'introducers': {} } connections = {'introducers': {} }
self.yaml_path.setContent(yamlutil.safe_dump(connections)) self.yaml_path.setContent(yamlutil.safe_dump(connections))
myclient = Client(self.basedir) myclient = create_client(self.basedir)
self.assertEquals(len(myclient.introducer_furls), 0) self.assertEquals(len(myclient.introducer_furls), 0)
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -9,9 +9,9 @@ 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 from allmydata.node import Node, formatTimeTahoeStyle, MissingConfigEntry, read_config, config_from_string
from allmydata.introducer.server import IntroducerNode from allmydata.introducer.server import create_introducer
from allmydata.client import Client from allmydata.client import create_client
from allmydata.util import fileutil, iputil from allmydata.util import fileutil, iputil
from allmydata.util.namespace import Namespace from allmydata.util.namespace import Namespace
import allmydata.test.common_util as testutil import allmydata.test.common_util as testutil
@ -23,7 +23,11 @@ class LoggingMultiService(service.MultiService):
class TestNode(Node): class TestNode(Node):
CERTFILE='DEFAULT_CERTFILE_BLANK' CERTFILE='DEFAULT_CERTFILE_BLANK'
PORTNUMFILE='DEFAULT_PORTNUMFILE_BLANK'
def __init__(self, basedir):
config = read_config(basedir, 'DEFAULT_PORTNUMFILE_BLANK')
Node.__init__(self, config, basedir)
class TestCase(testutil.SignalMixin, unittest.TestCase): class TestCase(testutil.SignalMixin, unittest.TestCase):
@ -198,7 +202,8 @@ class TestCase(testutil.SignalMixin, unittest.TestCase):
class EmptyNode(Node): class EmptyNode(Node):
def __init__(self): def __init__(self):
pass config = config_from_string("", "no portfile")
Node.__init__(self, config, 'no basedir')
EXPECTED = { EXPECTED = {
# top-level key is tub.port category # top-level key is tub.port category
@ -252,7 +257,7 @@ class PortLocation(unittest.TestCase):
n = EmptyNode() 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) fileutil.make_dirs(basedir)
n._portnumfile = os.path.join(basedir, "node.port") config = n.config = read_config(basedir, "node.port")
n._reveal_ip = True n._reveal_ip = True
if exp in ("ERR1", "ERR2", "ERR3", "ERR4"): if exp in ("ERR1", "ERR2", "ERR3", "ERR4"):
@ -281,7 +286,7 @@ class PortLocation(unittest.TestCase):
port, location = n.get_tub_portlocation(cfg_tubport, port, location = n.get_tub_portlocation(cfg_tubport,
cfg_location) cfg_location)
try: try:
with open(n._portnumfile, "r") as f: with open(config.portnum_fname, "r") as f:
saved_port = f.read().strip() saved_port = f.read().strip()
except EnvironmentError: except EnvironmentError:
saved_port = None saved_port = None
@ -367,7 +372,7 @@ class Listeners(unittest.TestCase):
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.read_config() n.config = read_config(n.basedir, "client.port")
n.check_privacy() n.check_privacy()
n.services = [] n.services = []
n.create_i2p_provider() n.create_i2p_provider()
@ -393,7 +398,7 @@ class Listeners(unittest.TestCase):
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.read_config() n.config = read_config(n.basedir, "client.port")
n.check_privacy() n.check_privacy()
n.services = [] n.services = []
i2p_ep = object() i2p_ep = object()
@ -420,7 +425,7 @@ class ClientNotListening(unittest.TestCase):
f.write(NOLISTEN) f.write(NOLISTEN)
f.write(DISABLE_STORAGE) f.write(DISABLE_STORAGE)
f.close() f.close()
n = Client(basedir) n = create_client(basedir)
self.assertEqual(n.tub.getListeners(), []) self.assertEqual(n.tub.getListeners(), [])
def test_disabled_but_storage(self): def test_disabled_but_storage(self):
@ -431,7 +436,7 @@ class ClientNotListening(unittest.TestCase):
f.write(NOLISTEN) f.write(NOLISTEN)
f.write(ENABLE_STORAGE) f.write(ENABLE_STORAGE)
f.close() f.close()
e = self.assertRaises(ValueError, Client, basedir) e = self.assertRaises(ValueError, create_client, basedir)
self.assertIn("storage is enabled, but tub is not listening", str(e)) self.assertIn("storage is enabled, but tub is not listening", str(e))
def test_disabled_but_helper(self): def test_disabled_but_helper(self):
@ -443,7 +448,7 @@ class ClientNotListening(unittest.TestCase):
f.write(DISABLE_STORAGE) f.write(DISABLE_STORAGE)
f.write(ENABLE_HELPER) f.write(ENABLE_HELPER)
f.close() f.close()
e = self.assertRaises(ValueError, Client, basedir) e = self.assertRaises(ValueError, create_client, basedir)
self.assertIn("helper is enabled, but tub is not listening", str(e)) self.assertIn("helper is enabled, but tub is not listening", str(e))
class IntroducerNotListening(unittest.TestCase): class IntroducerNotListening(unittest.TestCase):
@ -455,5 +460,5 @@ class IntroducerNotListening(unittest.TestCase):
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() f.close()
e = self.assertRaises(ValueError, IntroducerNode, 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

@ -9,7 +9,7 @@ from twisted.internet.defer import inlineCallbacks, returnValue
from allmydata.util import fileutil, pollmixin from allmydata.util import fileutil, pollmixin
from allmydata.util.encodingutil import unicode_to_argv, unicode_to_output, \ from allmydata.util.encodingutil import unicode_to_argv, unicode_to_output, \
get_filesystem_encoding get_filesystem_encoding
from allmydata.client import Client from allmydata.client import _Client
from allmydata.test import common_util from allmydata.test import common_util
import allmydata import allmydata
from allmydata import __appname__ from allmydata import __appname__
@ -337,7 +337,7 @@ class RunNode(common_util.SignalMixin, unittest.TestCase, pollmixin.PollMixin,
basedir = self.workdir("test_introducer") basedir = self.workdir("test_introducer")
c1 = os.path.join(basedir, "c1") c1 = os.path.join(basedir, "c1")
exit_trigger_file = os.path.join(c1, Client.EXIT_TRIGGER_FILE) exit_trigger_file = os.path.join(c1, _Client.EXIT_TRIGGER_FILE)
twistd_pid_file = os.path.join(c1, "twistd.pid") twistd_pid_file = os.path.join(c1, "twistd.pid")
introducer_furl_file = os.path.join(c1, "private", "introducer.furl") introducer_furl_file = os.path.join(c1, "private", "introducer.furl")
node_url_file = os.path.join(c1, "node.url") node_url_file = os.path.join(c1, "node.url")
@ -457,7 +457,7 @@ class RunNode(common_util.SignalMixin, unittest.TestCase, pollmixin.PollMixin,
basedir = self.workdir("test_client_no_noise") basedir = self.workdir("test_client_no_noise")
c1 = os.path.join(basedir, "c1") c1 = os.path.join(basedir, "c1")
exit_trigger_file = os.path.join(c1, Client.EXIT_TRIGGER_FILE) exit_trigger_file = os.path.join(c1, _Client.EXIT_TRIGGER_FILE)
twistd_pid_file = os.path.join(c1, "twistd.pid") twistd_pid_file = os.path.join(c1, "twistd.pid")
node_url_file = os.path.join(c1, "node.url") node_url_file = os.path.join(c1, "node.url")
@ -521,7 +521,7 @@ class RunNode(common_util.SignalMixin, unittest.TestCase, pollmixin.PollMixin,
basedir = self.workdir("test_client") basedir = self.workdir("test_client")
c1 = os.path.join(basedir, "c1") c1 = os.path.join(basedir, "c1")
exit_trigger_file = os.path.join(c1, Client.EXIT_TRIGGER_FILE) exit_trigger_file = os.path.join(c1, _Client.EXIT_TRIGGER_FILE)
twistd_pid_file = os.path.join(c1, "twistd.pid") twistd_pid_file = os.path.join(c1, "twistd.pid")
node_url_file = os.path.join(c1, "node.url") node_url_file = os.path.join(c1, "node.url")
storage_furl_file = os.path.join(c1, "private", "storage.furl") storage_furl_file = os.path.join(c1, "private", "storage.furl")

View File

@ -7,7 +7,7 @@ from twisted.application import service
import allmydata import allmydata
from allmydata import client, uri from allmydata import client, uri
from allmydata.introducer.server import IntroducerNode from allmydata.introducer.server import create_introducer
from allmydata.storage.mutable import MutableShareFile from allmydata.storage.mutable import MutableShareFile
from allmydata.storage.server import si_a2b from allmydata.storage.server import si_a2b
from allmydata.immutable import offloaded, upload from allmydata.immutable import offloaded, upload
@ -423,7 +423,7 @@ class SystemTestMixin(pollmixin.PollMixin, testutil.StallMixin):
f = open(os.path.join(iv_dir, "private", "node.pem"), "w") f = open(os.path.join(iv_dir, "private", "node.pem"), "w")
f.write(SYSTEM_TEST_CERTS[0]) f.write(SYSTEM_TEST_CERTS[0])
f.close() f.close()
iv = IntroducerNode(basedir=iv_dir) iv = create_introducer(basedir=iv_dir)
self.introducer = self.add_service(iv) self.introducer = self.add_service(iv)
self._get_introducer_web() self._get_introducer_web()
d = defer.succeed(None) d = defer.succeed(None)
@ -520,7 +520,7 @@ class SystemTestMixin(pollmixin.PollMixin, testutil.StallMixin):
# start clients[0], wait for it's tub to be ready (at which point it # start clients[0], wait for it's tub to be ready (at which point it
# will have registered the helper furl). # will have registered the helper furl).
c = self.add_service(client.Client(basedir=basedirs[0])) c = self.add_service(client.create_client(basedirs[0]))
self.clients.append(c) self.clients.append(c)
c.set_default_mutable_keysize(TEST_RSA_KEY_SIZE) c.set_default_mutable_keysize(TEST_RSA_KEY_SIZE)
@ -537,7 +537,7 @@ class SystemTestMixin(pollmixin.PollMixin, testutil.StallMixin):
# this starts the rest of the clients # this starts the rest of the clients
for i in range(1, self.numclients): for i in range(1, self.numclients):
c = self.add_service(client.Client(basedir=basedirs[i])) c = self.add_service(client.create_client(basedirs[i]))
self.clients.append(c) self.clients.append(c)
c.set_default_mutable_keysize(TEST_RSA_KEY_SIZE) c.set_default_mutable_keysize(TEST_RSA_KEY_SIZE)
log.msg("STARTING") log.msg("STARTING")
@ -569,7 +569,7 @@ class SystemTestMixin(pollmixin.PollMixin, testutil.StallMixin):
# better than blindly waiting for a second. # better than blindly waiting for a second.
d.addCallback(self.stall, 1.0) d.addCallback(self.stall, 1.0)
def _stopped(res): def _stopped(res):
new_c = client.Client(basedir=self.getdir("client%d" % num)) new_c = client.create_client(self.getdir("client%d" % num))
self.clients[num] = new_c self.clients[num] = new_c
new_c.set_default_mutable_keysize(TEST_RSA_KEY_SIZE) new_c.set_default_mutable_keysize(TEST_RSA_KEY_SIZE)
self.add_service(new_c) self.add_service(new_c)
@ -596,7 +596,7 @@ class SystemTestMixin(pollmixin.PollMixin, testutil.StallMixin):
config += "helper.furl = %s\n" % helper_furl config += "helper.furl = %s\n" % helper_furl
fileutil.write(os.path.join(basedir, 'tahoe.cfg'), config) fileutil.write(os.path.join(basedir, 'tahoe.cfg'), config)
c = client.Client(basedir=basedir) c = client.create_client(basedir)
self.clients.append(c) self.clients.append(c)
c.set_default_mutable_keysize(TEST_RSA_KEY_SIZE) c.set_default_mutable_keysize(TEST_RSA_KEY_SIZE)
self.numclients += 1 self.numclients += 1

View File

@ -20,7 +20,7 @@ from allmydata.util.happinessutil import servers_of_happiness, \
shares_by_server, merge_servers shares_by_server, merge_servers
from allmydata.storage_client import StorageFarmBroker from allmydata.storage_client import StorageFarmBroker
from allmydata.storage.server import storage_index_to_dir from allmydata.storage.server import storage_index_to_dir
from allmydata.client import Client from allmydata.client import _Client
MiB = 1024*1024 MiB = 1024*1024
@ -754,7 +754,7 @@ class ServerSelection(unittest.TestCase):
class StorageIndex(unittest.TestCase): class StorageIndex(unittest.TestCase):
def test_params_must_matter(self): def test_params_must_matter(self):
DATA = "I am some data" DATA = "I am some data"
PARAMS = Client.DEFAULT_ENCODING_PARAMETERS PARAMS = _Client.DEFAULT_ENCODING_PARAMETERS
u = upload.Data(DATA, convergence="") u = upload.Data(DATA, convergence="")
u.set_default_encoding_parameters(PARAMS) u.set_default_encoding_parameters(PARAMS)

View File

@ -1,7 +1,5 @@
import os.path
from twisted.trial import unittest from twisted.trial import unittest
from foolscap.api import fireEventually, flushEventualQueue from foolscap.api import fireEventually, flushEventualQueue
from allmydata.util import fileutil
from twisted.internet import defer from twisted.internet import defer
from allmydata.introducer import IntroducerNode from allmydata.introducer import IntroducerNode
from .common import FAVICON_MARKUP from .common import FAVICON_MARKUP
@ -20,14 +18,15 @@ class IntroducerWeb(unittest.TestCase):
@defer.inlineCallbacks @defer.inlineCallbacks
def test_welcome(self): def test_welcome(self):
basedir = "web.IntroducerWeb.test_welcome" config = (
os.mkdir(basedir) "[node]\n"
cfg = "\n".join(["[node]", "tub.location = 127.0.0.1:1\n"
"tub.location = 127.0.0.1:1", "web.port = tcp:0\n"
"web.port = tcp:0", )
]) + "\n" from allmydata.node import config_from_string
fileutil.write(os.path.join(basedir, "tahoe.cfg"), cfg) self.node = IntroducerNode(
self.node = IntroducerNode(basedir) config_from_string(config, portnumfile="introducer.port"),
)
self.ws = self.node.getServiceNamed("webish") self.ws = self.node.getServiceNamed("webish")
yield fireEventually(None) yield fireEventually(None)

View File

@ -46,7 +46,7 @@ from ..common_web import (
do_http, do_http,
Error, Error,
) )
from allmydata.client import Client, SecretHolder from allmydata.client import _Client, SecretHolder
from .common import unknown_rwcap, unknown_rocap, unknown_immcap, FAVICON_MARKUP from .common import unknown_rwcap, unknown_rocap, unknown_immcap, FAVICON_MARKUP
# create a fake uploader/downloader, and a couple of fake dirnodes, then # create a fake uploader/downloader, and a couple of fake dirnodes, then
# create a webserver that works against them # create a webserver that works against them
@ -238,7 +238,7 @@ class FakeStorageServer(service.MultiService):
def on_status_changed(self, cb): def on_status_changed(self, cb):
cb(self) cb(self)
class FakeClient(Client): class FakeClient(_Client):
def __init__(self): def __init__(self):
# don't upcall to Client.__init__, since we only want to initialize a # don't upcall to Client.__init__, since we only want to initialize a
# minimal subset # minimal subset

View File

@ -124,16 +124,16 @@ def create_config(reactor, cli_config):
# a nice error, and startService will throw an ugly error. # a nice error, and startService will throw an ugly error.
class Provider(service.MultiService): class Provider(service.MultiService):
def __init__(self, basedir, node_for_config, reactor): def __init__(self, basedir, config, reactor):
service.MultiService.__init__(self) service.MultiService.__init__(self)
self._basedir = basedir self._basedir = basedir
self._node_for_config = node_for_config self._config = config
self._i2p = _import_i2p() self._i2p = _import_i2p()
self._txi2p = _import_txi2p() self._txi2p = _import_txi2p()
self._reactor = reactor self._reactor = reactor
def _get_i2p_config(self, *args, **kwargs): def _get_i2p_config(self, *args, **kwargs):
return self._node_for_config.get_config("i2p", *args, **kwargs) return self._config.get_config("i2p", *args, **kwargs)
def get_listener(self): def get_listener(self):
# this is relative to BASEDIR, and our cwd should be BASEDIR # this is relative to BASEDIR, and our cwd should be BASEDIR