Add create-node CLI command, and make create-client equivalent to create-node --no-storage (fixes #760)

This commit is contained in:
david-sarah 2010-01-15 21:20:55 -08:00
parent 26ab58e006
commit 87f1bae7fe
10 changed files with 74 additions and 44 deletions

View File

@ -187,7 +187,7 @@ class SystemTest (object):
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.
@ -305,7 +305,7 @@ class SystemTest (object):
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:

View File

@ -16,9 +16,9 @@ The main file is named 'tahoe.cfg', which is an ".INI"-style configuration
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:
@ -51,9 +51,9 @@ web.port = (strports string, optional)
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.
@ -382,8 +382,8 @@ held while they are being received.
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

View File

@ -15,6 +15,7 @@ package), then the tahoe executable will be available somewhere else, perhaps
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.
@ -31,20 +32,25 @@ with the "allmydata" module (which contains the majority of the Tahoe
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
@ -56,15 +62,15 @@ generation to a separate process. Since RSA key generation takes several
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.
@ -91,9 +97,9 @@ local one.
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 ===

View File

@ -31,7 +31,7 @@ local host can connect. Using
"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 ==

View File

@ -239,7 +239,7 @@ to be set by end users.
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

View File

@ -5,8 +5,8 @@ from allmydata.scripts.common import BasedirMixin, NoDefaultBasedirMixin
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"),
@ -14,6 +14,8 @@ class CreateClientOptions(BasedirMixin, usage.Options):
("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"),
]
@ -81,7 +83,7 @@ def write_node_config(c, config):
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))
@ -127,13 +129,19 @@ def create_client(basedir, config, out=sys.stdout, err=sys.stderr):
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):
@ -152,15 +160,18 @@ def create_introducer(basedir, config, out=sys.stdout, err=sys.stderr):
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,
}

View File

@ -23,7 +23,6 @@ down the node after the test finishes.
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`

View File

@ -228,7 +228,7 @@ this file are ignored.
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")

View File

@ -42,7 +42,7 @@ class TheRightCode(common_util.SignalMixin, unittest.TestCase,
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.
@ -56,10 +56,10 @@ class CreateNode(unittest.TestCase):
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, "")
@ -67,6 +67,16 @@ class CreateNode(unittest.TestCase):
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.failIfEqual(rc, 0, str((out, err, rc)))
@ -79,18 +89,22 @@ class CreateNode(unittest.TestCase):
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")
@ -347,7 +361,7 @@ class RunNode(common_util.SignalMixin, unittest.TestCase, pollmixin.PollMixin,
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)

View File

@ -45,7 +45,7 @@ Filename: "{sys}\net.exe"; Parameters: "stop ""Allmydata SMB"""; Flags: runhidde
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