def test_config_utils(self): tahoe_cfg = self.create_tahoe_cfg("""\ [node] nickname = client-0 web.port = adopt-socket:fd=5 [storage] enabled = false """) # test that at least one option was read correctly config = configutil.get_config(tahoe_cfg) self.failUnlessEqual(config.get("node", "nickname"), "client-0") # test that set_config can mutate an existing option configutil.set_config(config, "node", "nickname", "Alice!") configutil.write_config(tahoe_cfg, config) config = configutil.get_config(tahoe_cfg) self.failUnlessEqual(config.get("node", "nickname"), "Alice!") # test that set_config can set a new option descriptor = "Twas brillig, and the slithy toves Did gyre and gimble in the wabe" configutil.set_config(config, "node", "descriptor", descriptor) configutil.write_config(tahoe_cfg, config) config = configutil.get_config(tahoe_cfg) self.failUnlessEqual(config.get("node", "descriptor"), descriptor)
def invite(options): if options.parent['node-directory']: basedir = argv_to_abspath(options.parent['node-directory']) else: basedir = get_default_nodedir() config = configutil.get_config(join(basedir, 'tahoe.cfg')) out = options.stdout err = options.stderr try: introducer_furl = get_introducer_furl(basedir, config) except Exception as e: print("Can't find introducer FURL for node '{}': {}".format(basedir, str(e)), file=err) raise SystemExit(1) nick = options['nick'] remote_config = { "shares-needed": options["shares-needed"] or config.get('client', 'shares.needed'), "shares-total": options["shares-total"] or config.get('client', 'shares.total'), "shares-happy": options["shares-happy"] or config.get('client', 'shares.happy'), "nickname": nick, "introducer": introducer_furl, } yield _send_config_via_wormhole(options, remote_config) print("Completed successfully", file=out)
def read_config(self): try: self.config = configutil.get_config(self.config_fname) except EnvironmentError: if os.path.exists(self.config_fname): raise
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 _upgrade_magic_folder_config(basedir): """ Helper that upgrades from single-magic-folder-only configs to multiple magic-folder configuration style (in YAML) """ config_fname = os.path.join(basedir, "tahoe.cfg") config = configutil.get_config(config_fname) collective_fname = os.path.join(basedir, "private", "collective_dircap") upload_fname = os.path.join(basedir, "private", "magic_folder_dircap") magic_folders = { u"default": { u"directory": config.get("magic_folder", "local.directory").decode("utf-8"), u"collective_dircap": fileutil.read(collective_fname), u"upload_dircap": fileutil.read(upload_fname), u"poll_interval": int(config.get("magic_folder", "poll_interval")), }, } fileutil.move_into_place( source=os.path.join(basedir, "private", "magicfolderdb.sqlite"), dest=os.path.join(basedir, "private", "magicfolder_default.sqlite"), ) save_magic_folders(basedir, magic_folders) config.remove_option("magic_folder", "local.directory") config.remove_option("magic_folder", "poll_interval") configutil.write_config(os.path.join(basedir, 'tahoe.cfg'), config) fileutil.remove_if_possible(collective_fname) fileutil.remove_if_possible(upload_fname)
def invite(options): if options.parent['node-directory']: basedir = argv_to_abspath(options.parent['node-directory']) else: basedir = get_default_nodedir() config = configutil.get_config(join(basedir, 'tahoe.cfg')) out = options.stdout err = options.stderr try: introducer_furl = get_introducer_furl(basedir, config) except Exception as e: print("Can't find introducer FURL for node '{}': {}".format( basedir, str(e)), file=err) raise SystemExit(1) nick = options['nick'] remote_config = { "shares-needed": options["shares-needed"] or config.get('client', 'shares.needed'), "shares-total": options["shares-total"] or config.get('client', 'shares.total'), "shares-happy": options["shares-happy"] or config.get('client', 'shares.happy'), "nickname": nick, "introducer": introducer_furl, } yield _send_config_via_wormhole(options, remote_config) print("Completed successfully", file=out)
def join(options): fields = options.invite_code.split(INVITE_SEPARATOR) if len(fields) != 2: raise usage.UsageError("Invalid invite code.") magic_readonly_cap, dmd_write_cap = fields dmd_cap_file = os.path.join(options["node-directory"], u"private", u"magic_folder_dircap") collective_readcap_file = os.path.join(options["node-directory"], u"private", u"collective_dircap") magic_folder_db_file = os.path.join(options["node-directory"], u"private", u"magicfolderdb.sqlite") if os.path.exists(dmd_cap_file) or os.path.exists( collective_readcap_file) or os.path.exists(magic_folder_db_file): print >> options.stderr, ( "\nThis client has already joined a magic folder." "\nUse the 'tahoe magic-folder leave' command first.\n") return 1 fileutil.write(dmd_cap_file, dmd_write_cap) fileutil.write(collective_readcap_file, magic_readonly_cap) config = configutil.get_config( os.path.join(options["node-directory"], u"tahoe.cfg")) configutil.set_config(config, "magic_folder", "enabled", "True") configutil.set_config(config, "magic_folder", "local.directory", options.local_dir.encode('utf-8')) configutil.set_config(config, "magic_folder", "poll_interval", options.get("poll-interval", "60")) configutil.write_config( os.path.join(options["node-directory"], u"tahoe.cfg"), config) return 0
def test_create_client_config(self): d = self.mktemp() os.mkdir(d) fname = os.path.join(d, 'tahoe.cfg') with open(fname, 'w') as f: opts = { "nickname": "nick", "webport": "tcp:3456", "hide-ip": False, "listen": "none", "shares-needed": "1", "shares-happy": "1", "shares-total": "1", } create_node.write_node_config(f, opts) create_node.write_client_config(f, opts) config = configutil.get_config(fname) # should succeed, no exceptions configutil.validate_config( fname, config, client._valid_config(), )
def test_duplicate_sections(self): """ Duplicate section names are merged. """ fname = self.create_tahoe_cfg('[node]\na = foo\n[node]\n b = bar\n') config = configutil.get_config(fname) self.assertEqual(config.get("node", "a"), "foo") self.assertEqual(config.get("node", "b"), "bar")
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 save_magic_folders(node_directory, folders): fileutil.write_atomically( os.path.join(node_directory, u"private", u"magic_folders.yaml"), yamlutil.safe_dump({u"magic-folders": folders}), ) config = configutil.get_config(os.path.join(node_directory, u"tahoe.cfg")) configutil.set_config(config, "magic_folder", "enabled", "True") configutil.write_config(os.path.join(node_directory, u"tahoe.cfg"), config)
def read_config(self): self.error_about_old_config_files() self.config = ConfigParser.SafeConfigParser() tahoe_cfg = os.path.join(self.basedir, "tahoe.cfg") try: self.config = configutil.get_config(tahoe_cfg) except EnvironmentError: if os.path.exists(tahoe_cfg): raise
def created(_): config_path = join(node_dir, 'tahoe.cfg') config = get_config(config_path) set_config( config, u'node', u'log_gatherer.furl', flog_gatherer.decode("utf-8"), ) write_config(FilePath(config_path), config)
def test_config_validation_success(self): fname = self.create_tahoe_cfg('[node]\nvalid = foo\n') config = configutil.get_config(fname) # should succeed, no exceptions configutil.validate_config( fname, config, self.static_valid_config, )
def test_config_validation_success(self): d = self.mktemp() os.mkdir(d) fname = os.path.join(d, 'tahoe.cfg') with open(fname, 'w') as f: f.write('[node]\nvalid = foo\n') config = configutil.get_config(fname) # should succeed, no exceptions configutil.validate_config(fname, config, dict(node=['valid']))
def test_config_validation_invalid_item(self): fname = self.create_tahoe_cfg('[node]\nvalid = foo\ninvalid = foo\n') config = configutil.get_config(fname) e = self.assertRaises( configutil.UnknownConfigError, configutil.validate_config, fname, config, self.static_valid_config, ) self.assertIn("section [node] contains unknown option 'invalid'", str(e))
def test_config_utils(self): self.basedir = "cli/ConfigUtilTests/test-config-utils" self.set_up_grid() tahoe_cfg = os.path.join(self.get_clientdir(i=0), "tahoe.cfg") # test that at least one option was read correctly config = configutil.get_config(tahoe_cfg) self.failUnlessEqual(config.get("node", "nickname"), "client-0") # test that set_config can mutate an existing option configutil.set_config(config, "node", "nickname", "Alice!") configutil.write_config(tahoe_cfg, config) config = configutil.get_config(tahoe_cfg) self.failUnlessEqual(config.get("node", "nickname"), "Alice!") # test that set_config can set a new option descriptor = "Twas brillig, and the slithy toves Did gyre and gimble in the wabe" configutil.set_config(config, "node", "descriptor", descriptor) configutil.write_config(tahoe_cfg, config) config = configutil.get_config(tahoe_cfg) self.failUnlessEqual(config.get("node", "descriptor"), descriptor)
def test_config_utils(self): self.basedir = "cli/ConfigUtilTests/test-config-utils" self.set_up_grid(oneshare=True) tahoe_cfg = os.path.join(self.get_clientdir(i=0), "tahoe.cfg") # test that at least one option was read correctly config = configutil.get_config(tahoe_cfg) self.failUnlessEqual(config.get("node", "nickname"), "client-0") # test that set_config can mutate an existing option configutil.set_config(config, "node", "nickname", "Alice!") configutil.write_config(tahoe_cfg, config) config = configutil.get_config(tahoe_cfg) self.failUnlessEqual(config.get("node", "nickname"), "Alice!") # test that set_config can set a new option descriptor = "Twas brillig, and the slithy toves Did gyre and gimble in the wabe" configutil.set_config(config, "node", "descriptor", descriptor) configutil.write_config(tahoe_cfg, config) config = configutil.get_config(tahoe_cfg) self.failUnlessEqual(config.get("node", "descriptor"), descriptor)
def test_config_dynamic_validation_success(self): """ A configuration with sections and items that are not matched by the static validation but are matched by the dynamic validation is considered valid. """ fname = self.create_tahoe_cfg('[node]\nvalid = foo\n') config = configutil.get_config(fname) # should succeed, no exceptions configutil.validate_config( fname, config, self.dynamic_valid_config, )
def test_config_dynamic_validation_invalid_item(self): """ A configuration with a section, item pair that is matched by neither the static nor dynamic validators is rejected. """ fname = self.create_tahoe_cfg('[node]\nvalid = foo\ninvalid = foo\n') config = configutil.get_config(fname) e = self.assertRaises( configutil.UnknownConfigError, configutil.validate_config, fname, config, self.dynamic_valid_config, ) self.assertIn("section [node] contains unknown option 'invalid'", str(e))
def test_config_validation_invalid_section(self): d = self.mktemp() os.mkdir(d) fname = os.path.join(d, 'tahoe.cfg') with open(fname, 'w') as f: f.write('[node]\nvalid = foo\n[invalid]\n') config = configutil.get_config(fname) e = self.assertRaises( configutil.UnknownConfigError, configutil.validate_config, fname, config, dict(node=['valid']), ) self.assertIn("contains unknown section [invalid]", str(e))
def test_create_client_config(self): d = self.mktemp() os.mkdir(d) fname = os.path.join(d, 'tahoe.cfg') with open(fname, 'w') as f: opts = {"nickname": "nick", "webport": "tcp:3456", "hide-ip": False, "listen": "none", } create_node.write_node_config(f, opts) create_node.write_client_config(f, opts) config = configutil.get_config(fname) # should succeed, no exceptions configutil.validate_config(fname, config, client._valid_config_sections())
def maybe_upgrade_magic_folders(node_directory): """ If the given node directory is not already using the new-style magic-folder config it will be upgraded to do so. (This should only be done if the user is running a command that needs to modify the config) """ yaml_fname = os.path.join(node_directory, u"private", u"magic_folders.yaml") if os.path.exists(yaml_fname): # we already have new-style magic folders return config_fname = os.path.join(node_directory, "tahoe.cfg") config = configutil.get_config(config_fname) # we have no YAML config; if we have config in tahoe.cfg then we # can upgrade it to the YAML-based configuration if config.has_option("magic_folder", "local.directory"): _upgrade_magic_folder_config(node_directory)
def read_config(basedir, portnumfile, generated_files=[], _valid_config_sections=None): """ Read and validate configuration. :param unicode basedir: directory where configuration data begins :param unicode portnumfile: filename fragment for "port number" files :param list generated_files: a list of automatically-generated configuration files. :param dict _valid_config_sections: (internal use, optional) a dict-of-dicts structure defining valid configuration sections and keys :returns: :class:`allmydata.node._Config` instance """ 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 as e: if e.errno != errno.ENOENT: raise configutil.validate_config(config_fname, parser, _valid_config_sections()) # make sure we have a private configuration area fileutil.make_dirs(os.path.join(basedir, "private"), 0o700) return _Config(parser, portnumfile, basedir, config_fname)
def read_config(basedir, portnumfile, generated_files=[], _valid_config=None): """ Read and validate configuration. :param unicode basedir: directory where configuration data begins :param unicode portnumfile: filename fragment for "port number" files :param list generated_files: a list of automatically-generated configuration files. :param ValidConfiguration _valid_config: (internal use, optional) a structure defining valid configuration sections and keys :returns: :class:`allmydata.node._Config` instance """ basedir = abspath_expanduser_unicode(ensure_text(basedir)) if _valid_config is None: _valid_config = _common_valid_config() # 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") try: parser = configutil.get_config(config_fname) except EnvironmentError as e: if e.errno != errno.ENOENT: raise # The file is missing, just create empty ConfigParser. parser = configutil.get_config_from_string(u"") configutil.validate_config(config_fname, parser, _valid_config) # make sure we have a private configuration area fileutil.make_dirs(os.path.join(basedir, "private"), 0o700) return _Config(parser, portnumfile, basedir, config_fname)
def read_config(self): self.error_about_old_config_files() self.config = ConfigParser.SafeConfigParser() tahoe_cfg = os.path.join(self.basedir, "tahoe.cfg") try: self.config = configutil.get_config(tahoe_cfg) except EnvironmentError: if os.path.exists(tahoe_cfg): raise cfg_tubport = self.get_config("node", "tub.port", "") if not cfg_tubport: # For 'tub.port', tahoe.cfg overrides the individual file on # disk. So only read self._portnumfile if tahoe.cfg doesn't # provide a value. try: file_tubport = fileutil.read(self._portnumfile).strip() configutil.set_config(self.config, "node", "tub.port", file_tubport) except EnvironmentError: if os.path.exists(self._portnumfile): raise
def join(options): fields = options.invite_code.split(INVITE_SEPARATOR) if len(fields) != 2: raise usage.UsageError("Invalid invite code.") magic_readonly_cap, dmd_write_cap = fields dmd_cap_file = os.path.join(options["node-directory"], u"private", u"magic_folder_dircap") collective_readcap_file = os.path.join(options["node-directory"], u"private", u"collective_dircap") magic_folder_db_file = os.path.join(options["node-directory"], u"private", u"magicfolderdb.sqlite") if os.path.exists(dmd_cap_file) or os.path.exists(collective_readcap_file) or os.path.exists(magic_folder_db_file): print >>options.stderr, ("\nThis client has already joined a magic folder." "\nUse the 'tahoe magic-folder leave' command first.\n") return 1 fileutil.write(dmd_cap_file, dmd_write_cap) fileutil.write(collective_readcap_file, magic_readonly_cap) config = configutil.get_config(os.path.join(options["node-directory"], u"tahoe.cfg")) configutil.set_config(config, "magic_folder", "enabled", "True") configutil.set_config(config, "magic_folder", "local.directory", options.local_dir.encode('utf-8')) configutil.write_config(os.path.join(options["node-directory"], u"tahoe.cfg"), config) return 0
def load_magic_folders(node_directory): """ Loads existing magic-folder configuration and returns it as a dict mapping name -> dict of config. This will NOT upgrade from old-style to new-style config (but WILL read old-style config and return in the same way as if it was new-style). :returns: dict mapping magic-folder-name to its config (also a dict) """ yaml_fname = os.path.join(node_directory, u"private", u"magic_folders.yaml") folders = dict() config_fname = os.path.join(node_directory, "tahoe.cfg") config = configutil.get_config(config_fname) if not os.path.exists(yaml_fname): # there will still be a magic_folder section in a "new" # config, but it won't have local.directory nor poll_interval # in it. if config.has_option("magic_folder", "local.directory"): up_fname = os.path.join(node_directory, "private", "magic_folder_dircap") coll_fname = os.path.join(node_directory, "private", "collective_dircap") directory = config.get("magic_folder", "local.directory").decode('utf8') try: interval = int(config.get("magic_folder", "poll_interval")) except ConfigParser.NoOptionError: interval = 60 dir_fp = to_filepath(directory) if not dir_fp.exists(): raise Exception( "The '[magic_folder] local.directory' parameter is {} " "but there is no directory at that location.".format( quote_local_unicode_path(directory), ) ) if not dir_fp.isdir(): raise Exception( "The '[magic_folder] local.directory' parameter is {} " "but the thing at that location is not a directory.".format( quote_local_unicode_path(directory) ) ) folders[u"default"] = { u"directory": directory, u"upload_dircap": fileutil.read(up_fname), u"collective_dircap": fileutil.read(coll_fname), u"poll_interval": interval, } else: # without any YAML file AND no local.directory option it's # an error if magic-folder is "enabled" because we don't # actually have enough config for any magic-folders at all if config.has_section("magic_folder") \ and config.getboolean("magic_folder", "enabled") \ and not folders: raise Exception( "[magic_folder] is enabled but has no YAML file and no " "'local.directory' option." ) elif os.path.exists(yaml_fname): # yaml config-file exists if config.has_option("magic_folder", "local.directory"): raise Exception( "magic-folder config has both old-style configuration" " and new-style configuration; please remove the " "'local.directory' key from tahoe.cfg or remove " "'magic_folders.yaml' from {}".format(node_directory) ) with open(yaml_fname, "r") as f: magic_folders = yamlutil.safe_load(f.read()) if not isinstance(magic_folders, dict): raise Exception( "'{}' should contain a dict".format(yaml_fname) ) folders = magic_folders['magic-folders'] if not isinstance(folders, dict): raise Exception( "'magic-folders' in '{}' should be a dict".format(yaml_fname) ) # check configuration for (name, mf_config) in folders.items(): if not isinstance(mf_config, dict): raise Exception( "Each item in '{}' must itself be a dict".format(yaml_fname) ) for k in ['collective_dircap', 'upload_dircap', 'directory', 'poll_interval']: if k not in mf_config: raise Exception( "Config for magic folder '{}' is missing '{}'".format( name, k ) ) for k in ['collective_dircap', 'upload_dircap']: if isinstance(mf_config[k], unicode): mf_config[k] = mf_config[k].encode('ascii') return folders
def created(_): config_path = join(node_dir, 'tahoe.cfg') config = get_config(config_path) set_config(config, 'node', 'log_gatherer.furl', flog_gatherer) write_config(config_path, config)
def _create_node(reactor, tahoe_venv, request, base_dir, introducer_furl, flog_gatherer, name, web_port, storage=True, magic_text=None, needed=2, happy=3, total=4): """ Helper to create a single node, run it and return the instance spawnProcess returned (ITransport) """ node_dir = join(base_dir, name) if web_port is None: web_port = '' if not exists(node_dir): print("creating", node_dir) mkdir(node_dir) done_proto = _ProcessExitedProtocol() args = [ 'create-node', '--nickname', name, '--introducer', introducer_furl, '--hostname', 'localhost', '--listen', 'tcp', '--webport', web_port, '--shares-needed', "{}".format(needed), '--shares-happy', "{}".format(happy), '--shares-total', "{}".format(total), '--helper', ] if not storage: args.append('--no-storage') args.append(node_dir) _tahoe_runner(done_proto, reactor, tahoe_venv, request, args) yield done_proto.done if flog_gatherer: config_path = join(node_dir, 'tahoe.cfg') config = get_config(config_path) set_config(config, 'node', 'log_gatherer.furl', flog_gatherer) write_config(config_path, config) magic_text = "client running" action_fields = { "action_type": u"integration:tahoe-node:service", "node": name, } process = yield run_tahoe_service(reactor, request, action_fields, magic_text, tahoe_venv, node_dir) returnValue(process)
def read_config(basedir): tahoe_cfg = os.path.join(basedir, "tahoe.cfg") config = configutil.get_config(tahoe_cfg) return config