From 87f1bae7fe715da15390fa4ce3501df10df34625 Mon Sep 17 00:00:00 2001 From: david-sarah Date: Fri, 15 Jan 2010 21:20:55 -0800 Subject: [PATCH] Add create-node CLI command, and make create-client equivalent to create-node --no-storage (fixes #760) --- contrib/fuse/runtests.py | 4 ++-- docs/configuration.txt | 16 +++++++------- docs/frontends/CLI.txt | 32 ++++++++++++++++----------- docs/frontends/webapi.txt | 2 +- docs/proposed/accounting-overview.txt | 2 +- src/allmydata/scripts/create_node.py | 25 +++++++++++++++------ src/allmydata/test/check_grid.py | 1 - src/allmydata/test/check_memory.py | 2 +- src/allmydata/test/test_runner.py | 32 +++++++++++++++++++-------- windows/installer.tmpl | 2 +- 10 files changed, 74 insertions(+), 44 deletions(-) diff --git a/contrib/fuse/runtests.py b/contrib/fuse/runtests.py index 7d13a504..58dfb5b4 100644 --- a/contrib/fuse/runtests.py +++ b/contrib/fuse/runtests.py @@ -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: diff --git a/docs/configuration.txt b/docs/configuration.txt index 1e4b248a..aed14c7f 100644 --- a/docs/configuration.txt +++ b/docs/configuration.txt @@ -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 diff --git a/docs/frontends/CLI.txt b/docs/frontends/CLI.txt index e452924f..de64b241 100644 --- a/docs/frontends/CLI.txt +++ b/docs/frontends/CLI.txt @@ -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 === diff --git a/docs/frontends/webapi.txt b/docs/frontends/webapi.txt index 91c2aa30..e955933b 100644 --- a/docs/frontends/webapi.txt +++ b/docs/frontends/webapi.txt @@ -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 == diff --git a/docs/proposed/accounting-overview.txt b/docs/proposed/accounting-overview.txt index 230813b1..91351fc5 100644 --- a/docs/proposed/accounting-overview.txt +++ b/docs/proposed/accounting-overview.txt @@ -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 diff --git a/src/allmydata/scripts/create_node.py b/src/allmydata/scripts/create_node.py index 7a20ded1..f47ccc99 100644 --- a/src/allmydata/scripts/create_node.py +++ b/src/allmydata/scripts/create_node.py @@ -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, } diff --git a/src/allmydata/test/check_grid.py b/src/allmydata/test/check_grid.py index b1deea0f..30d29fcd 100644 --- a/src/allmydata/test/check_grid.py +++ b/src/allmydata/test/check_grid.py @@ -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` diff --git a/src/allmydata/test/check_memory.py b/src/allmydata/test/check_memory.py index 40cfa590..31c66c8a 100644 --- a/src/allmydata/test/check_memory.py +++ b/src/allmydata/test/check_memory.py @@ -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") diff --git a/src/allmydata/test/test_runner.py b/src/allmydata/test/test_runner.py index 4d07e626..bd604a57 100644 --- a/src/allmydata/test/test_runner.py +++ b/src/allmydata/test/test_runner.py @@ -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) diff --git a/windows/installer.tmpl b/windows/installer.tmpl index daf0e4af..6721ed99 100644 --- a/windows/installer.tmpl +++ b/windows/installer.tmpl @@ -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 -- 2.45.2