pull 'basedir' entirely into _Config

Put all config-related methods into _Config; change
code to ask config for paths instead of using basedir;
add some better docstrings
This commit is contained in:
meejah 2018-01-31 11:30:46 -07:00
parent f80e61fef6
commit 7685fb34cd
5 changed files with 66 additions and 56 deletions

View File

@ -181,8 +181,9 @@ def read_config(basedir, portnumfile, generated_files=[]):
)
# this method is async
# @defer.inlineCallbacks
def create_client(basedir=u".", _client_factory=None):
def create_client(basedir=u"."):
"""
Creates a new client instance (a subclass of Node).
@ -195,9 +196,6 @@ def create_client(basedir=u".", _client_factory=None):
:returns: :class:`allmydata.client._Client` instance (or whatever
`_client_factory` returns)
"""
from allmydata.node import read_config, create_connection_handlers, create_tub_options
from allmydata.node import create_main_tub, create_control_tub, create_tub
# should we check for this directory existing first? (this used to
# be in Node's constructor)
node.create_node_dir(basedir, CLIENT_README)
@ -206,14 +204,20 @@ def create_client(basedir=u".", _client_factory=None):
if _client_factory is None:
_client_factory = _Client
# pre-requisites
# read config file and create instance
config = read_config(basedir, u"client.port", _valid_config_sections=_valid_config_sections)
return create_client_from_config(config)
return create_client_from_config(config) # async
# this can/should be async
# this method is async
# @defer.inlineCallbacks
def create_client_from_config(config):
"""
Create a new _Client instance given a _Config instance (basedir
must already exist and be writable).
Most code should probably use `create_client` instead.
"""
i2p_provider = create_i2p_provider(reactor, config)
tor_provider = create_tor_provider(reactor, config)
handlers = create_connection_handlers(reactor, config, i2p_provider, tor_provider)
@ -221,12 +225,12 @@ def create_client_from_config(config):
tub_options = create_tub_options(config)
main_tub, is_listening = create_main_tub(
basedir, config, tub_options, default_connection_handlers,
config, tub_options, default_connection_handlers,
foolscap_connection_handlers, i2p_provider, tor_provider,
)
control_tub = create_control_tub()
introducer_clients, introducer_furls = create_introducer_clients(basedir, config, main_tub)
introducer_clients, introducer_furls = create_introducer_clients(config, main_tub)
storage_broker = create_storage_farm_broker(
config, default_connection_handlers, foolscap_connection_handlers,
tub_options, introducer_clients
@ -241,7 +245,6 @@ def create_client_from_config(config):
introducer_clients,
introducer_furls,
storage_broker,
basedir,
tub_is_listening=is_listening,
)
i2p_provider.setServiceParent(client)
@ -258,42 +261,58 @@ def _sequencer(config):
seqnum_s = "0"
seqnum = int(seqnum_s.strip())
seqnum += 1 # increment
node._write_config(config.get_config_path(), "announcement-seqnum", "%d\n" % seqnum)
config.write_config_file("announcement-seqnum", "{}\n".format(seqnum))
nonce = _make_secret().strip()
return seqnum, nonce
def create_introducer_clients(basedir, config, main_tub):
def create_introducer_clients(config, main_tub):
"""
returns a 2-tuple containing two lists: introducer_clients,
introducer_furls
"""
# (probably makes sense to return a list of 2-tuples instead of a
# 2-tuple of lists, but keeping variable names etc from when this
# was self.init_introducer_clients in Node)
# Returns both of these:
introducer_clients = []
introducer_furls = []
introducers_yaml_filename = os.path.join(basedir, "private", "introducers.yaml")
introducers_yaml_filename = config.get_private_path("introducers.yaml")
introducers_filepath = FilePath(introducers_yaml_filename)
try:
with introducers_filepath.open() as f:
introducers_yaml = yamlutil.safe_load(f)
introducers = introducers_yaml.get("introducers", {})
log.msg("found %d introducers in private/introducers.yaml" %
len(introducers))
log.msg(
"found {} introducers in private/introducers.yaml".format(
len(introducers),
)
)
except EnvironmentError:
introducers = {}
if "default" in introducers.keys():
raise ValueError("'default' introducer furl cannot be specified in introducers.yaml; please fix impossible configuration.")
raise ValueError(
"'default' introducer furl cannot be specified in introducers.yaml;"
" please fix impossible configuration."
)
# read furl from tahoe.cfg
tahoe_cfg_introducer_furl = config.get_config("client", "introducer.furl", None)
if tahoe_cfg_introducer_furl == "None":
raise ValueError("tahoe.cfg has invalid 'introducer.furl = None':"
" to disable it, use 'introducer.furl ='"
" or omit the key entirely")
raise ValueError(
"tahoe.cfg has invalid 'introducer.furl = None':"
" to disable it, use 'introducer.furl ='"
" or omit the key entirely"
)
if tahoe_cfg_introducer_furl:
introducers[u'default'] = {'furl':tahoe_cfg_introducer_furl}
for petname, introducer in introducers.items():
introducer_cache_filepath = FilePath(os.path.join(basedir, "private", "introducer_{}_cache.yaml".format(petname)))
introducer_cache_filepath = FilePath(config.get_private_path("introducer_{}_cache.yaml".format(petname)))
ic = IntroducerClient(
main_tub,
introducer['furl'].encode("ascii"),

View File

@ -53,10 +53,10 @@ def create_introducer(basedir=u"."):
_valid_config_sections=_valid_config_sections,
)
i2p_provider = create_i2p_provider(reactor, basedir, config)
tor_provider = create_tor_provider(reactor, basedir, config)
i2p_provider = create_i2p_provider(reactor, config)
tor_provider = create_tor_provider(reactor, config)
default_connection_handlers, foolscap_connection_handlers = create_connection_handlers(reactor, basedir, config, i2p_provider, tor_provider)
default_connection_handlers, foolscap_connection_handlers = create_connection_handlers(reactor, config, i2p_provider, tor_provider)
tub_options = create_tub_options(config)
# we don't remember these because the Introducer doesn't make
@ -64,7 +64,7 @@ def create_introducer(basedir=u"."):
i2p_provider = None
tor_provider = None
main_tub, is_listening = create_main_tub(
basedir, config, tub_options, default_connection_handlers,
config, tub_options, default_connection_handlers,
foolscap_connection_handlers, i2p_provider, tor_provider,
)
control_tub = create_control_tub()
@ -75,7 +75,6 @@ def create_introducer(basedir=u"."):
control_tub,
i2p_provider,
tor_provider,
basedir,
tub_is_listening=is_listening,
)
return defer.succeed(node)

View File

@ -281,6 +281,18 @@ class _Config(object):
"Unable to write config file '{}'".format(fn),
)
def write_config_file(self, name, value, mode="w"):
"""
writes the given 'value' into a file called 'name' in the config
directory
"""
fn = os.path.join(self._basedir, name)
try:
fileutil.write(fn, value, mode)
except EnvironmentError as e:
log.msg("Unable to write config file '{}'".format(fn))
log.err(e)
def get_config(self, section, option, default=_None, boolean=False):
try:
if boolean:
@ -497,18 +509,6 @@ def create_tub(tub_options, default_connection_handlers, foolscap_connection_han
return tub
def _write_config(basedir, name, value, mode="w"):
"""
Write a string to a config file.
"""
fn = os.path.join(basedir, name)
try:
fileutil.write(fn, value, mode)
except EnvironmentError, e:
log.msg("Unable to write config file '{}'".format(fn))
log.err(e)
def _convert_tub_port(s):
if re.search(r'^\d+$', s):
return "tcp:{}".format(int(s))
@ -593,7 +593,7 @@ def _tub_portlocation(config, cfg_tubport, cfg_location):
return tubport, location
def create_main_tub(basedir, config, tub_options,
def create_main_tub(config, tub_options,
default_connection_handlers, foolscap_connection_handlers,
i2p_provider, tor_provider,
handler_overrides={}, cert_filename="node.pem"):
@ -601,7 +601,7 @@ def create_main_tub(basedir, config, tub_options,
cfg_location = config.get_config("node", "tub.location", None)
portlocation = _tub_portlocation(config, cfg_tubport, cfg_location)
certfile = os.path.join(basedir, "private", "node.pem") # FIXME "node.pem" was the CERTFILE option/thing
certfile = config.get_private_path("node.pem") # FIXME? "node.pem" was the CERTFILE option/thing
tub = create_tub(tub_options, default_connection_handlers, foolscap_connection_handlers,
handler_overrides=handler_overrides, certFile=certfile)
@ -679,17 +679,11 @@ class Node(service.MultiService):
self.logSource = "Node"
self.setup_logging()
# XXX do we need to save these? or does just "create_client"
# need them? (note: look in client.py also!)
# (client.py DOES use them in init_client_storage_broker, but
# we'll want to pull that out as well...so FIXME later)
## self._default_connection_handlers, self._foolscap_connection_handlers = create_connection_handlers(reactor, basedir, config)
self.tub = main_tub
if self.tub is not None:
self.nodeid = b32decode(self.tub.tubID.upper()) # binary format
self.short_nodeid = b32encode(self.nodeid).lower()[:8] # for printing
self.write_config("my_nodeid", b32encode(self.nodeid).lower() + "\n")
self.config.write_config_file("my_nodeid", b32encode(self.nodeid).lower() + "\n")
self.tub.setServiceParent(self) # is this okay in __init__?
else:
self.nodeid = self.short_nodeid = None
@ -734,12 +728,6 @@ class Node(service.MultiService):
self.log("Log Tub location set to %s" % (location,))
self.log_tub.setServiceParent(self)
# XXX this should be deprecated; no reason for it to be a method;
# use _write_config() instead
def write_config(self, name, value, mode="w"):
"""Write a string to a config file."""
_write_config(self.basedir, name, value, mode=mode)
def startService(self):
# Note: this class can be started and stopped at most once.
self.log("Node.startService")

View File

@ -8,7 +8,7 @@ from twisted.internet.error import ConnectionRefusedError, ConnectError
from twisted.application import service
def create(reactor, basedir, config):
def create(reactor, config):
"""
Create a new Provider service (this is an IService so must be
hooked up to a parent or otherwise started).
@ -18,7 +18,7 @@ def create(reactor, basedir, config):
to start an I2P Destination too, then this `create()` method will
throw a nice error (and startService will throw an ugly error).
"""
provider = _Provider(basedir, config, reactor)
provider = _Provider(config, reactor)
provider.check_dest_config()
return provider

View File

@ -11,7 +11,7 @@ from .observer import OneShotObserverList
from .iputil import allocate_tcp_port
def create(reactor, basedir, config):
def create(reactor, config):
"""
Create a new _Provider service (this is an IService so must be
hooked up to a parent or otherwise started).
@ -21,7 +21,7 @@ def create(reactor, basedir, config):
to start an onion service too, then this `create()` method will
throw a nice error (and startService will throw an ugly error).
"""
provider = _Provider(basedir, config, reactor)
provider = _Provider(config, reactor)
provider.check_onion_config()
return provider
@ -266,7 +266,11 @@ class _Provider(service.MultiService):
# this fires with a tuple of (control_endpoint, tor_protocol)
if not self._tor_launched:
self._tor_launched = OneShotObserverList()
<<<<<<< HEAD
private_dir = self._config.get_config_path("private")
=======
private_dir = os.path.join(self._config._basedir, "private")
>>>>>>> pull 'basedir' entirely into _Config
tor_binary = self._get_tor_config("tor.executable", None)
d = _launch_tor(reactor, tor_binary, private_dir, self._txtorcon)
d.addBoth(self._tor_launched.fire)