self.clientbase = None
## Top-level flow control:
- # These "*_layer" methods call eachother in a linear fashion, using
+ # These "*_layer" methods call each other in a linear fashion, using
# exception unwinding to do cleanup properly. Each "layer" invokes
# a deeper layer, and each layer does its own cleanup upon exit.
base = os.path.join(self.testroot, 'client_%d' % (clientnum,))
- output = self.run_tahoe('create-client', '--basedir', base)
+ output = self.run_tahoe('create-node', '--basedir', base)
self.check_tahoe_output(output, ExpectedCreationOutput, base)
if clientnum == 0:
file (parsed by the Python stdlib 'ConfigParser' module: "[name]" section
markers, lines with "key.subkey: value", rfc822-style continuations). There
are other files that contain information which does not easily fit into this
-format. The 'tahoe create-client' command will create an initial tahoe.cfg
-file for you. After creation, the node will never modify the 'tahoe.cfg'
-file: all persistent state is put in other files.
+format. The 'tahoe create-node' or 'tahoe create-client' command will create
+an initial tahoe.cfg file for you. After creation, the node will never modify
+the 'tahoe.cfg' file: all persistent state is put in other files.
The item descriptions below use the following types:
This controls where the node's webserver should listen, providing filesystem
access and node status as defined in webapi.txt . This file contains a
Twisted "strports" specification such as "3456" or
- "tcp:3456:interface=127.0.0.1". The 'tahoe create-client' command sets the
- web.port to "tcp:3456:interface=127.0.0.1" by default, and is overridable by
- the "--webport" option. You can make it use SSL by writing
+ "tcp:3456:interface=127.0.0.1". The 'tahoe create-node' or 'tahoe create-client'
+ commands set the web.port to "tcp:3456:interface=127.0.0.1" by default; this
+ is overridable by the "--webport" option. You can make it use SSL by writing
"ssl:3456:privateKey=mykey.pem:certKey=cert.pem" instead.
If this is not provided, the node will not run a web server.
client.tac : this file defines the client, by constructing the actual Client
instance each time the node is started. It is used by the 'twistd'
daemonization program (in the "-y" mode), which is run internally by the
-"tahoe start" command. This file is created by the "tahoe create-client"
-command.
+"tahoe start" command. This file is created by the "tahoe create-node" or
+"tahoe create-client" commands.
private/control.furl : this file contains a FURL that provides access to a
control port on the client node, from which files can be uploaded and
in /usr/bin/tahoe . In this case, it will use your platform's normal
PYTHONPATH search paths to find the tahoe code and other libraries.
+
== CLI Command Overview ==
The "tahoe" tool provides access to three categories of commands.
functionality) and including versions for a number of dependent libraries,
like Twisted, Foolscap, pycryptopp, and zfec.
+
== Node Management ==
-"tahoe create-client [NODEDIR]" is the basic make-a-new-node command. It
+"tahoe create-node [NODEDIR]" is the basic make-a-new-node command. It
creates a new directory and populates it with files that will allow the
"tahoe start" command to use it later on. This command creates nodes that
have client functionality (upload/download files), web API services
-(controlled by the 'webport' file), and storage services (controlled by
-"no_storage" and the like).
+(controlled by the 'webport' file), and storage services (unless
+"--no_storage" is specified).
-NODEDIR defaults to ~/.tahoe/ , and newly-created clients default to
+NODEDIR defaults to ~/.tahoe/ , and newly-created nodes default to
publishing a web server on port 3456 (limited to the loopback interface, at
127.0.0.1, to restrict access to other programs on the same host). All of the
other "tahoe" subcommands use corresponding defaults.
+"tahoe create-client [NODEDIR]" creates a node with no storage service.
+That is, it behaves like "tahoe create-node --no-storage [NODEDIR]".
+(This is a change from versions prior to 1.6.0.)
+
"tahoe create-introducer [NODEDIR]" is used to create the Introducer node.
This node provides introduction services and nothing else. When started, this
node will produce an introducer.furl, which should be published to all
seconds, and must be done each time a directory is created, moving it to a
separate process allows the first process (perhaps a busy wapi server) to
continue servicing other requests. The key generator exports a FURL that can
-be copied into a client node to enable this functionality.
+be copied into a node to enable this functionality.
+
+"tahoe run [NODEDIR]" will start a previously-created node in the foreground.
"tahoe start [NODEDIR]" will launch a previously-created node. It will launch
the node into the background, using the standard Twisted "twistd"
-daemon-launching tool.
-
-"tahoe run [NODEDIR]" will start a previous-created node in the foreground.
-Some platforms are unable to run a daemon in the background: this command
-provides a way to use a tahoe node on such platforms.
+daemon-launching tool. On some platforms (including Windows) this command is
+unable to run a daemon in the background; in that case it behaves in the
+same way as "tahoe run".
"tahoe stop [NODEDIR]" will shut down a running node.
These commands also use a table of "aliases" to figure out which directory
they ought to use a starting point. This is explained in more detail below.
-In Tahoe v1.3.0, passing non-ascii characters to the cli is not guaranteed to
-work, although it might work on your platform, especially if your platform
-uses utf-8 encoding.
+In Tahoe up to v1.6.0, passing non-ASCII characters to the CLI is not guaranteed
+to work, although it might work on your platform, especially if your platform
+uses UTF-8 encoding.
=== Starting Directories ===
"ssl:3456:privateKey=mykey.pem:certKey=cert.pem" runs an SSL server.
This webport can be set when the node is created by passing a --webport
-option to the 'tahoe create-client' command. By default, the node listens on
+option to the 'tahoe create-node' command. By default, the node listens on
port 3456, on the loopback (127.0.0.1) interface.
== Basic Concepts ==
The process starts with Bob the storage server operator, who has just created
a new Storage Server:
- tahoe create-client
+ tahoe create-node
--> creates ~/.tahoe
# edit ~/.tahoe/tahoe.cfg, add introducer.furl, configure storage, etc
class CreateClientOptions(BasedirMixin, usage.Options):
optParameters = [
- ("basedir", "C", None, "which directory to create the client in"),
- # we provide create-client -time options for the most common
+ ("basedir", "C", None, "which directory to create the node in"),
+ # we provide 'create-node'-time options for the most common
# configuration knobs. The rest can be controlled by editing
# tahoe.cfg before node startup.
("nickname", "n", None, "nickname for this node"),
("webport", "p", "tcp:3456:interface=127.0.0.1",
"which TCP port to run the HTTP interface on. Use 'none' to disable."),
]
+
+class CreateNodeOptions(CreateClientOptions):
optFlags = [
("no-storage", None, "do not offer storage service to other nodes"),
]
c.write("\n")
-def create_client(basedir, config, out=sys.stdout, err=sys.stderr):
+def create_node(basedir, config, out=sys.stdout, err=sys.stderr):
if os.path.exists(basedir):
if os.listdir(basedir):
print >>err, "The base directory \"%s\", which is \"%s\" is not empty." % (basedir, os.path.abspath(basedir))
from allmydata.util import fileutil
fileutil.make_dirs(os.path.join(basedir, "private"), 0700)
- print >>out, "client created in %s" % basedir
+ print >>out, "Node created in %s" % basedir
if not config.get("introducer", ""):
print >>out, " Please set [client]introducer.furl= in tahoe.cfg!"
print >>out, " The node cannot connect to a grid without it."
if not config.get("nickname", ""):
print >>out, " Please set [node]nickname= in tahoe.cfg"
+
+def create_client(basedir, config, out=sys.stdout, err=sys.stderr):
+ config['no-storage'] = True
+ return create_node(basedir, config, out=out, err=err)
+
+
def create_introducer(basedir, config, out=sys.stdout, err=sys.stderr):
if os.path.exists(basedir):
if os.listdir(basedir):
write_node_config(c, config)
c.close()
- print >>out, "introducer created in %s" % basedir
+ print >>out, "Introducer created in %s" % basedir
+
subCommands = [
- ["create-client", None, CreateClientOptions, "Create a client node."],
- ["create-introducer", None, CreateIntroducerOptions, "Create a introducer node."],
+ ["create-node", None, CreateNodeOptions, "Create a node that acts as a client, server or both."],
+ ["create-client", None, CreateClientOptions, "Create a client node (with storage initially disabled)."],
+ ["create-introducer", None, CreateIntroducerOptions, "Create an introducer."],
]
dispatch = {
+ "create-node": create_node,
"create-client": create_client,
"create-introducer": create_introducer,
}
To set up the client node, do the following:
tahoe create-client DIR
- touch DIR/no_storage
populate DIR/introducer.furl
tahoe start DIR
tahoe add-alias -d DIR testgrid `tahoe mkdir -d DIR`
log.msg("MAKING CLIENT")
clientdir = self.clientdir = os.path.join(self.testdir, "client")
quiet = StringIO()
- create_node.create_client(clientdir, {}, out=quiet)
+ create_node.create_node(clientdir, {}, out=quiet)
log.msg("DONE MAKING CLIENT")
f = open(os.path.join(clientdir, "introducer.furl"), "w")
f.write(self.introducer_furl + "\n")
return d
class CreateNode(unittest.TestCase):
- # exercise "tahoe create-client", create-introducer,
+ # exercise "tahoe create-node", create-introducer,
# create-key-generator, and create-stats-gatherer, by calling the
# corresponding code as a subroutine.
rc = runner.runner(argv, stdout=out, stderr=err)
return rc, out.getvalue(), err.getvalue()
- def test_client(self):
- basedir = self.workdir("test_client")
- c1 = os.path.join(basedir, "c1")
- argv = ["--quiet", "create-client", "--basedir", c1]
+ def test_node(self, command="create-node"):
+ basedir = self.workdir("test_node")
+ c1 = os.path.join(basedir, command + "-c1")
+ argv = ["--quiet", command, "--basedir", c1]
rc, out, err = self.run_tahoe(argv)
self.failUnlessEqual(err, "")
self.failUnlessEqual(out, "")
self.failUnlessEqual(rc, 0)
self.failUnless(os.path.exists(c1))
self.failUnless(os.path.exists(os.path.join(c1, "tahoe-client.tac")))
+
+ # tahoe.cfg should exist, and should have storage enabled for
+ # 'create-node', and disabled for 'create-client'.
+ tahoe_cfg = os.path.join(c1, "tahoe.cfg")
+ self.failUnless(os.path.exists(tahoe_cfg))
+ content = open(tahoe_cfg).read()
+ if command == "create-client":
+ self.failUnless("\n[storage]\nenabled = false\n" in content)
+ else:
+ self.failUnless("\n[storage]\nenabled = true\n" in content)
# creating the client a second time should be rejected
rc, out, err = self.run_tahoe(argv)
self.failIf(re.search("[\S][^\.!?]$", line), (line,))
# test that the non --basedir form works too
- c2 = os.path.join(basedir, "c2")
- argv = ["--quiet", "create-client", c2]
+ c2 = os.path.join(basedir, command + "c2")
+ argv = ["--quiet", command, c2]
rc, out, err = self.run_tahoe(argv)
self.failUnless(os.path.exists(c2))
self.failUnless(os.path.exists(os.path.join(c2, "tahoe-client.tac")))
# make sure it rejects too many arguments
- argv = ["create-client", "basedir", "extraarg"]
+ argv = [command, "basedir", "extraarg"]
self.failUnlessRaises(usage.UsageError,
runner.runner, argv,
run_by_human=False)
+ def test_client(self):
+ # create-client should behave like create-node --no-storage.
+ self.test_node(command="create-client")
+
def test_introducer(self):
basedir = self.workdir("test_introducer")
c1 = os.path.join(basedir, "c1")
TWISTD_PID_FILE = os.path.join(c1, "twistd.pid")
PORTNUMFILE = os.path.join(c1, "client.port")
- d = utils.getProcessOutputAndValue(bintahoe, args=["--quiet", "create-client", "--basedir", c1, "--webport", "0"], env=os.environ)
+ d = utils.getProcessOutputAndValue(bintahoe, args=["--quiet", "create-node", "--basedir", c1, "--webport", "0"], env=os.environ)
def _cb(res):
out, err, rc_or_sig = res
self.failUnlessEqual(rc_or_sig, 0)
Filename: "{sys}\net.exe"; Parameters: "stop Tahoe"; Flags: runhidden
Filename: "{sys}\net.exe"; Parameters: "stop Allmydata Manager"; Flags: runhidden
Filename: "{app}\Install\tahoesvc.exe"; Parameters: "-install -auto"; Flags: runhidden
-Filename: "{app}\Install\tahoe.exe"; Parameters: "create-client ""{app}\noderoot"""; Flags: runhidden
+Filename: "{app}\Install\tahoe.exe"; Parameters: "create-node ""{app}\noderoot"""; Flags: runhidden
Filename: "{app}\Install\winfuse\AllmydataManager.exe"; Parameters: "-install -auto"; Flags: runhidden
Filename: "{app}\Install\winfuse\InstallUtil.exe"; Parameters: """{app}\Install\winfuse\WinFUSE.exe"""; Flags: runhidden
Filename: "{app}\Install\confwiz.exe"; Flags: hidewizard