Add create-node CLI command, and make create-client equivalent to create-node --no-storage (fixes #760)
This commit is contained in:
parent
26ab58e006
commit
87f1bae7fe
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 ===
|
||||
|
||||
|
|
|
@ -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 ==
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -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`
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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,16 +56,26 @@ 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, "")
|
||||
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)
|
||||
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue