diff --git a/src/allmydata/client.py b/src/allmydata/client.py index 07aa24068..12e9297f0 100644 --- a/src/allmydata/client.py +++ b/src/allmydata/client.py @@ -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"), diff --git a/src/allmydata/introducer/server.py b/src/allmydata/introducer/server.py index f9f7bb224..eee4cde93 100644 --- a/src/allmydata/introducer/server.py +++ b/src/allmydata/introducer/server.py @@ -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) diff --git a/src/allmydata/node.py b/src/allmydata/node.py index 6e9d11cf5..77ceddba8 100644 --- a/src/allmydata/node.py +++ b/src/allmydata/node.py @@ -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") diff --git a/src/allmydata/util/i2p_provider.py b/src/allmydata/util/i2p_provider.py index c9cd69ed3..37789c428 100644 --- a/src/allmydata/util/i2p_provider.py +++ b/src/allmydata/util/i2p_provider.py @@ -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 diff --git a/src/allmydata/util/tor_provider.py b/src/allmydata/util/tor_provider.py index dc9e411ce..b786d6a6b 100644 --- a/src/allmydata/util/tor_provider.py +++ b/src/allmydata/util/tor_provider.py @@ -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)