Changeset 39628cb in trunk


Ignore:
Timestamp:
2020-12-14T19:58:35Z (4 years ago)
Author:
GitHub <noreply@…>
Branches:
master
Children:
035cd8b, 7458ea63, a9bcd62
Parents:
052d95f (diff), bdb7c50 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
git-author:
Jean-Paul Calderone <exarkun@…> (2020-12-14 19:58:35)
git-committer:
GitHub <noreply@…> (2020-12-14 19:58:35)
Message:

Merge pull request #921 from tahoe-lafs/3550.remove-start-stop-restart-daemonize

remove start stop restart daemonize

Fixes: ticket:3550
Fixes: ticket:3523
Fixes: ticket:3524

Files:
3 added
7 deleted
15 edited

Legend:

Unmodified
Added
Removed
  • TabularUnified docs/anonymity-configuration.rst

    r052d95f r39628cb  
    274274    tcp = tor
    275275
    276 * Launch the Tahoe server with ``tahoe start $NODEDIR``
     276* Launch the Tahoe server with ``tahoe run $NODEDIR``
    277277
    278278The ``tub.port`` section will cause the Tahoe server to listen on PORT, but
     
    436436performance of your Tahoe-LAFS node, because your I2P router will always
    437437prioritize your own traffic.
    438 
  • TabularUnified docs/configuration.rst

    r052d95f r39628cb  
    366366
    367367    When False, any of the following configuration problems will cause
    368     ``tahoe start`` to throw a PrivacyError instead of starting the node:
     368    ``tahoe run`` to throw a PrivacyError instead of starting the node:
    369369
    370370    * ``[node] tub.location`` contains any ``tcp:`` hints
  • TabularUnified docs/frontends/CLI.rst

    r052d95f r39628cb  
    8686"``tahoe create-node [NODEDIR]``" is the basic make-a-new-node
    8787command. It creates a new directory and populates it with files that
    88 will allow the "``tahoe start``" and related commands to use it later
     88will allow the "``tahoe run``" and related commands to use it later
    8989on. ``tahoe create-node`` creates nodes that have client functionality
    9090(upload/download files), web API services (controlled by the
     
    9595publishing a web server on port 3456 (limited to the loopback interface, at
    9696127.0.0.1, to restrict access to other programs on the same host). All of the
    97 other "``tahoe``" subcommands use corresponding defaults (with the exception
    98 that "``tahoe run``" defaults to running a node in the current directory).
     97other "``tahoe``" subcommands use corresponding defaults.
    9998
    10099"``tahoe create-client [NODEDIR]``" creates a node with no storage service.
     
    117116the process as a daemon, it is recommended that you use your favourite
    118117daemonization tool.
    119 
    120 The now-deprecated "``tahoe start [NODEDIR]``" command will launch a
    121 previously-created node. It will launch the node into the background
    122 using ``tahoe daemonize`` (and internal-only command, not for user
    123 use). On some platforms (including Windows) this command is unable to
    124 run a daemon in the background; in that case it behaves in the same
    125 way as "``tahoe run``". ``tahoe start`` also monitors the logs for up
    126 to 5 seconds looking for either a succesful startup message or for
    127 early failure messages and produces an appropriate exit code.  You are
    128 encouraged to use ``tahoe run`` along with your favourite
    129 daemonization tool instead of this. ``tahoe start`` is maintained for
    130 backwards compatibility of users already using it; new scripts should
    131 depend on ``tahoe run``.
    132 
    133 "``tahoe stop [NODEDIR]``" will shut down a running node. "``tahoe
    134 restart [NODEDIR]``" will stop and then restart a running
    135 node. Similar to above, you should use ``tahoe run`` instead alongside
    136 your favourite daemonization tool.
    137 
    138118
    139119File Store Manipulation
  • TabularUnified docs/frontends/webapi.rst

    r052d95f r39628cb  
    21462146 -> storage index: whpepioyrnff7orecjolvbudeu
    21472147 echo "whpepioyrnff7orecjolvbudeu my puppy told me to" >>$NODEDIR/access.blacklist
    2148  tahoe restart $NODEDIR
     2148 # ... restart the node to re-read configuration ...
    21492149 tahoe get URI:CHK:n7r3m6wmomelk4sep3kw5cvduq:os7ijw5c3maek7pg65e5254k2fzjflavtpejjyhshpsxuqzhcwwq:3:20:14861
    21502150 -> error, 403 Access Prohibited: my puppy told me to
  • TabularUnified docs/logging.rst

    r052d95f r39628cb  
    129129Tahoe source code.
    130130
    131 The incident gatherer is created with the "``flogtool
    132 create-incident-gatherer WORKDIR``" command, and started with "``tahoe
    133 start``". The generated "``gatherer.tac``" file should be modified to add
    134 classifier functions.
     131The incident gatherer is created with the "``flogtool create-incident-gatherer
     132WORKDIR``" command, and started with "``tahoe run``". The generated
     133"``gatherer.tac``" file should be modified to add classifier functions.
    135134
    136135The incident gatherer writes incident names (which are simply the relative
     
    176175
    177176Create the Log Gatherer with the "``flogtool create-gatherer WORKDIR``"
    178 command, and start it with "``tahoe start``". Then copy the contents of the
     177command, and start it with "``twistd -ny gatherer.tac``". Then copy the contents of the
    179178``log_gatherer.furl`` file it creates into the ``BASEDIR/tahoe.cfg`` file
    180179(under the key ``log_gatherer.furl`` of the section ``[node]``) of all nodes
  • TabularUnified docs/running.rst

    r052d95f r39628cb  
    8282
    8383The “``tahoe run``” command above will run the node in the foreground.
    84 On Unix, you can run it in the background instead by using the
    85 “``tahoe start``” command. To stop a node started in this way, use
    86 “``tahoe stop``”. ``tahoe --help`` gives a summary of all commands.
     84``tahoe --help`` gives a summary of all commands.
    8785
    8886
     
    10098of the directory is up to you), ``cd`` into it, and run “``tahoe
    10199create-introducer --hostname=example.net .``” (but using the hostname of
    102 your VPS). Now run the introducer using “``tahoe start .``”. After it
     100your VPS). Now run the introducer using “``tahoe run .``”. After it
    103101starts, it will write a file named ``introducer.furl`` into the
    104102``private/`` subdirectory of that base directory. This file contains the
    105103URL the other nodes must use in order to connect to this introducer.
    106 (Note that “``tahoe run .``” doesn't work for introducers, this is a
    107 known issue: `#937`_.)
    108104
    109105You can distribute your Introducer fURL securely to new clients by using
  • TabularUnified integration/conftest.py

    r052d95f r39628cb  
    202202        f.write(config)
    203203
    204     # on windows, "tahoe start" means: run forever in the foreground,
    205     # but on linux it means daemonize. "tahoe run" is consistent
    206     # between platforms.
     204    # "tahoe run" is consistent across Linux/macOS/Windows, unlike the old
     205    # "start" command.
    207206    protocol = _MagicTextProtocol('introducer running')
    208207    transport = _tahoe_runner_optional_coverage(
     
    279278        f.write(config)
    280279
    281     # on windows, "tahoe start" means: run forever in the foreground,
    282     # but on linux it means daemonize. "tahoe run" is consistent
    283     # between platforms.
     280    # "tahoe run" is consistent across Linux/macOS/Windows, unlike the old
     281    # "start" command.
    284282    protocol = _MagicTextProtocol('introducer running')
    285283    transport = _tahoe_runner_optional_coverage(
  • TabularUnified integration/util.py

    r052d95f r39628cb  
    190190    protocol = _MagicTextProtocol(magic_text)
    191191
    192     # on windows, "tahoe start" means: run forever in the foreground,
    193     # but on linux it means daemonize. "tahoe run" is consistent
    194     # between platforms.
    195 
     192    # "tahoe run" is consistent across Linux/macOS/Windows, unlike the old
     193    # "start" command.
    196194    transport = _tahoe_runner_optional_coverage(
    197195        protocol,
  • TabularUnified src/allmydata/scripts/common.py

    r052d95f r39628cb  
    3838        self.command_name = os.path.basename(sys.argv[0])
    3939
    40     # Only allow "tahoe --version", not e.g. "tahoe start --version"
     40    # Only allow "tahoe --version", not e.g. "tahoe <cmd> --version"
    4141    def opt_version(self):
    4242        raise usage.UsageError("--version not allowed on subcommands")
  • TabularUnified src/allmydata/scripts/runner.py

    r052d95f r39628cb  
    1010from allmydata.scripts.common import get_default_nodedir
    1111from allmydata.scripts import debug, create_node, cli, \
    12     admin, tahoe_daemonize, tahoe_start, \
    13     tahoe_stop, tahoe_restart, tahoe_run, tahoe_invite
     12    admin, tahoe_run, tahoe_invite
    1413from allmydata.util.encodingutil import quote_output, quote_local_unicode_path, get_io_encoding
    1514from allmydata.util.eliotutil import (
     
    3837# XXX all this 'dispatch' stuff needs to be unified + fixed up
    3938_control_node_dispatch = {
    40     "daemonize": tahoe_daemonize.daemonize,
    41     "start": tahoe_start.start,
    4239    "run": tahoe_run.run,
    43     "stop": tahoe_stop.stop,
    44     "restart": tahoe_restart.restart,
    4540}
    4641
    4742process_control_commands = [
    4843    ["run", None, tahoe_run.RunOptions, "run a node without daemonizing"],
    49     ["daemonize", None, tahoe_daemonize.DaemonizeOptions, "(deprecated) run a node in the background"],
    50     ["start", None, tahoe_start.StartOptions, "(deprecated) start a node in the background and confirm it started"],
    51     ["stop", None, tahoe_stop.StopOptions, "(deprecated) stop a node"],
    52     ["restart", None, tahoe_restart.RestartOptions, "(deprecated) restart a node"],
    5344]
    5445
  • TabularUnified src/allmydata/scripts/tahoe_run.py

    r052d95f r39628cb  
    1 from .run_common import (
    2     RunOptions as _RunOptions,
    3     run,
    4 )
     1from __future__ import print_function
    52
    63__all__ = [
     
    96]
    107
    11 class RunOptions(_RunOptions):
     8import os, sys
     9from allmydata.scripts.common import BasedirOptions
     10from twisted.scripts import twistd
     11from twisted.python import usage
     12from twisted.python.reflect import namedAny
     13from twisted.internet.defer import maybeDeferred
     14from twisted.application.service import Service
     15
     16from allmydata.scripts.default_nodedir import _default_nodedir
     17from allmydata.util.encodingutil import listdir_unicode, quote_local_unicode_path
     18from allmydata.util.configutil import UnknownConfigError
     19from allmydata.util.deferredutil import HookMixin
     20
     21
     22def get_pidfile(basedir):
     23    """
     24    Returns the path to the PID file.
     25    :param basedir: the node's base directory
     26    :returns: the path to the PID file
     27    """
     28    return os.path.join(basedir, u"twistd.pid")
     29
     30def get_pid_from_pidfile(pidfile):
     31    """
     32    Tries to read and return the PID stored in the node's PID file
     33    (twistd.pid).
     34    :param pidfile: try to read this PID file
     35    :returns: A numeric PID on success, ``None`` if PID file absent or
     36              inaccessible, ``-1`` if PID file invalid.
     37    """
     38    try:
     39        with open(pidfile, "r") as f:
     40            pid = f.read()
     41    except EnvironmentError:
     42        return None
     43
     44    try:
     45        pid = int(pid)
     46    except ValueError:
     47        return -1
     48
     49    return pid
     50
     51def identify_node_type(basedir):
     52    """
     53    :return unicode: None or one of: 'client' or 'introducer'.
     54    """
     55    tac = u''
     56    try:
     57        for fn in listdir_unicode(basedir):
     58            if fn.endswith(u".tac"):
     59                tac = fn
     60                break
     61    except OSError:
     62        return None
     63
     64    for t in (u"client", u"introducer"):
     65        if t in tac:
     66            return t
     67    return None
     68
     69
     70class RunOptions(BasedirOptions):
    1271    subcommand_name = "run"
    1372
    14     def postOptions(self):
    15         self.twistd_args += ("--nodaemon",)
     73    optParameters = [
     74        ("basedir", "C", None,
     75         "Specify which Tahoe base directory should be used."
     76         " This has the same effect as the global --node-directory option."
     77         " [default: %s]" % quote_local_unicode_path(_default_nodedir)),
     78        ]
     79
     80    def parseArgs(self, basedir=None, *twistd_args):
     81        # This can't handle e.g. 'tahoe run --reactor=foo', since
     82        # '--reactor=foo' looks like an option to the tahoe subcommand, not to
     83        # twistd. So you can either use 'tahoe run' or 'tahoe run NODEDIR
     84        # --TWISTD-OPTIONS'. Note that 'tahoe --node-directory=NODEDIR run
     85        # --TWISTD-OPTIONS' also isn't allowed, unfortunately.
     86
     87        BasedirOptions.parseArgs(self, basedir)
     88        self.twistd_args = twistd_args
     89
     90    def getSynopsis(self):
     91        return ("Usage:  %s [global-options] %s [options]"
     92                " [NODEDIR [twistd-options]]"
     93                % (self.command_name, self.subcommand_name))
     94
     95    def getUsage(self, width=None):
     96        t = BasedirOptions.getUsage(self, width) + "\n"
     97        twistd_options = str(MyTwistdConfig()).partition("\n")[2].partition("\n\n")[0]
     98        t += twistd_options.replace("Options:", "twistd-options:", 1)
     99        t += """
     100
     101Note that if any twistd-options are used, NODEDIR must be specified explicitly
     102(not by default or using -C/--basedir or -d/--node-directory), and followed by
     103the twistd-options.
     104"""
     105        return t
     106
     107
     108class MyTwistdConfig(twistd.ServerOptions):
     109    subCommands = [("DaemonizeTahoeNode", None, usage.Options, "node")]
     110
     111    stderr = sys.stderr
     112
     113
     114class DaemonizeTheRealService(Service, HookMixin):
     115    """
     116    this HookMixin should really be a helper; our hooks:
     117
     118    - 'running': triggered when startup has completed; it triggers
     119        with None of successful or a Failure otherwise.
     120    """
     121    stderr = sys.stderr
     122
     123    def __init__(self, nodetype, basedir, options):
     124        super(DaemonizeTheRealService, self).__init__()
     125        self.nodetype = nodetype
     126        self.basedir = basedir
     127        # setup for HookMixin
     128        self._hooks = {
     129            "running": None,
     130        }
     131        self.stderr = options.parent.stderr
     132
     133    def startService(self):
     134
     135        def start():
     136            node_to_instance = {
     137                u"client": lambda: maybeDeferred(namedAny("allmydata.client.create_client"), self.basedir),
     138                u"introducer": lambda: maybeDeferred(namedAny("allmydata.introducer.server.create_introducer"), self.basedir),
     139            }
     140
     141            try:
     142                service_factory = node_to_instance[self.nodetype]
     143            except KeyError:
     144                raise ValueError("unknown nodetype %s" % self.nodetype)
     145
     146            def handle_config_error(reason):
     147                if reason.check(UnknownConfigError):
     148                    self.stderr.write("\nConfiguration error:\n{}\n\n".format(reason.value))
     149                else:
     150                    self.stderr.write("\nUnknown error\n")
     151                    reason.printTraceback(self.stderr)
     152                reactor.stop()
     153
     154            d = service_factory()
     155
     156            def created(srv):
     157                srv.setServiceParent(self.parent)
     158            d.addCallback(created)
     159            d.addErrback(handle_config_error)
     160            d.addBoth(self._call_hook, 'running')
     161            return d
     162
     163        from twisted.internet import reactor
     164        reactor.callWhenRunning(start)
     165
     166
     167class DaemonizeTahoeNodePlugin(object):
     168    tapname = "tahoenode"
     169    def __init__(self, nodetype, basedir):
     170        self.nodetype = nodetype
     171        self.basedir = basedir
     172
     173    def makeService(self, so):
     174        return DaemonizeTheRealService(self.nodetype, self.basedir, so)
     175
     176
     177def run(config):
     178    """
     179    Runs a Tahoe-LAFS node in the foreground.
     180
     181    Sets up the IService instance corresponding to the type of node
     182    that's starting and uses Twisted's twistd runner to disconnect our
     183    process from the terminal.
     184    """
     185    out = config.stdout
     186    err = config.stderr
     187    basedir = config['basedir']
     188    quoted_basedir = quote_local_unicode_path(basedir)
     189    print("'tahoe {}' in {}".format(config.subcommand_name, quoted_basedir), file=out)
     190    if not os.path.isdir(basedir):
     191        print("%s does not look like a directory at all" % quoted_basedir, file=err)
     192        return 1
     193    nodetype = identify_node_type(basedir)
     194    if not nodetype:
     195        print("%s is not a recognizable node directory" % quoted_basedir, file=err)
     196        return 1
     197    # Now prepare to turn into a twistd process. This os.chdir is the point
     198    # of no return.
     199    os.chdir(basedir)
     200    twistd_args = ["--nodaemon"]
     201    twistd_args.extend(config.twistd_args)
     202    twistd_args.append("DaemonizeTahoeNode") # point at our DaemonizeTahoeNodePlugin
     203
     204    twistd_config = MyTwistdConfig()
     205    twistd_config.stdout = out
     206    twistd_config.stderr = err
     207    try:
     208        twistd_config.parseOptions(twistd_args)
     209    except usage.error as ue:
     210        # these arguments were unsuitable for 'twistd'
     211        print(config, file=err)
     212        print("tahoe %s: usage error from twistd: %s\n" % (config.subcommand_name, ue), file=err)
     213        return 1
     214    twistd_config.loadedPlugins = {"DaemonizeTahoeNode": DaemonizeTahoeNodePlugin(nodetype, basedir)}
     215
     216    # handle invalid PID file (twistd might not start otherwise)
     217    pidfile = get_pidfile(basedir)
     218    if get_pid_from_pidfile(pidfile) == -1:
     219        print("found invalid PID file in %s - deleting it" % basedir, file=err)
     220        os.remove(pidfile)
     221
     222    # We always pass --nodaemon so twistd.runApp does not daemonize.
     223    print("running node in %s" % (quoted_basedir,), file=out)
     224    twistd.runApp(twistd_config)
     225    return 0
  • TabularUnified src/allmydata/test/check_grid.py

    r052d95f r39628cb  
    1717functional.
    1818
    19 This script expects that the client node will be not running when the script
    20 starts, but it will forcibly shut down the node just to be sure. It will shut
    21 down the node after the test finishes.
     19This script expects the client node to be running already.
    2220
    2321To set up the client node, do the following:
    2422
    25   tahoe create-client DIR
    26   populate DIR/introducer.furl
    27   tahoe start DIR
    28   tahoe add-alias -d DIR testgrid `tahoe mkdir -d DIR`
    29   pick a 10kB-ish test file, compute its md5sum
    30   tahoe put -d DIR FILE testgrid:old.MD5SUM
    31   tahoe put -d DIR FILE testgrid:recent.MD5SUM
    32   tahoe put -d DIR FILE testgrid:recentdir/recent.MD5SUM
    33   echo "" | tahoe put -d DIR --mutable testgrid:log
    34   echo "" | tahoe put -d DIR --mutable testgrid:recentlog
     23  tahoe create-client --introducer=INTRODUCER_FURL DIR
     24  tahoe run DIR
     25  tahoe -d DIR create-alias testgrid
     26  # pick a 10kB-ish test file, compute its md5sum
     27  tahoe -d DIR put FILE testgrid:old.MD5SUM
     28  tahoe -d DIR put FILE testgrid:recent.MD5SUM
     29  tahoe -d DIR put FILE testgrid:recentdir/recent.MD5SUM
     30  echo "" | tahoe -d DIR put --mutable - testgrid:log
     31  echo "" | tahoe -d DIR put --mutable - testgrid:recentlog
    3532
    3633This script will perform the following steps (the kind of compatibility that
     
    5350This script will also keep track of speeds and latencies and will write them
    5451in a machine-readable logfile.
    55 
    5652"""
    5753
     
    105101    def cli(self, cmd, *args, **kwargs):
    106102        print("tahoe", cmd, " ".join(args))
    107         stdout, stderr = self.command(self.tahoe, cmd, "-d", self.nodedir,
     103        stdout, stderr = self.command(self.tahoe, "-d", self.nodedir, cmd,
    108104                                      *args, **kwargs)
    109105        if not kwargs.get("ignore_stderr", False) and stderr != "":
     
    111107                                                                 stderr))
    112108        return stdout
    113 
    114     def stop_old_node(self):
    115         print("tahoe stop", self.nodedir, "(force)")
    116         self.command(self.tahoe, "stop", self.nodedir, expected_rc=None)
    117 
    118     def start_node(self):
    119         print("tahoe start", self.nodedir)
    120         self.command(self.tahoe, "start", self.nodedir)
    121         time.sleep(5)
    122 
    123     def stop_node(self):
    124         print("tahoe stop", self.nodedir)
    125         self.command(self.tahoe, "stop", self.nodedir)
    126109
    127110    def read_and_check(self, f):
     
    205188        return fn, data
    206189
    207     def run(self):
    208         self.stop_old_node()
    209         self.start_node()
    210         try:
    211             self.do_test()
    212         finally:
    213             self.stop_node()
    214 
    215190def main():
    216191    config = GridTesterOptions()
    217192    config.parseOptions()
    218193    gt = GridTester(config)
    219     gt.run()
     194    gt.do_test()
    220195
    221196if __name__ == "__main__":
  • TabularUnified src/allmydata/test/cli/test_cli.py

    r052d95f r39628cb  
    2121
    2222# Test that the scripts can be imported.
    23 from allmydata.scripts import create_node, debug, tahoe_start, tahoe_restart, \
     23from allmydata.scripts import create_node, debug, \
    2424    tahoe_add_alias, tahoe_backup, tahoe_check, tahoe_cp, tahoe_get, tahoe_ls, \
    2525    tahoe_manifest, tahoe_mkdir, tahoe_mv, tahoe_put, tahoe_unlink, tahoe_webopen, \
    26     tahoe_stop, tahoe_daemonize, tahoe_run
    27 _hush_pyflakes = [create_node, debug, tahoe_start, tahoe_restart, tahoe_stop,
     26    tahoe_run
     27_hush_pyflakes = [create_node, debug,
    2828    tahoe_add_alias, tahoe_backup, tahoe_check, tahoe_cp, tahoe_get, tahoe_ls,
    2929    tahoe_manifest, tahoe_mkdir, tahoe_mv, tahoe_put, tahoe_unlink, tahoe_webopen,
    30     tahoe_daemonize, tahoe_run]
     30    tahoe_run]
    3131
    3232from allmydata.scripts import common
     
    627627        self.failUnlessIn("[options]", help)
    628628
    629     def test_start(self):
    630         help = str(tahoe_start.StartOptions())
    631         self.failUnlessIn("[options] [NODEDIR [twistd-options]]", help)
    632 
    633     def test_stop(self):
    634         help = str(tahoe_stop.StopOptions())
    635         self.failUnlessIn("[options] [NODEDIR]", help)
    636 
    637     def test_restart(self):
    638         help = str(tahoe_restart.RestartOptions())
    639         self.failUnlessIn("[options] [NODEDIR [twistd-options]]", help)
    640 
    641629    def test_run(self):
    642630        help = str(tahoe_run.RunOptions())
     
    12701258        # but "tahoe SUBCOMMAND --version" should be rejected
    12711259        self.failUnlessRaises(usage.UsageError, self.parse,
    1272                               ["start", "--version"])
     1260                              ["run", "--version"])
    12731261        self.failUnlessRaises(usage.UsageError, self.parse,
    1274                               ["start", "--version-and-path"])
     1262                              ["run", "--version-and-path"])
    12751263
    12761264    def test_quiet(self):
    12771265        # accepted as an overall option, but not on subcommands
    1278         o = self.parse(["--quiet", "start"])
     1266        o = self.parse(["--quiet", "run"])
    12791267        self.failUnless(o.parent["quiet"])
    12801268        self.failUnlessRaises(usage.UsageError, self.parse,
    1281                               ["start", "--quiet"])
     1269                              ["run", "--quiet"])
    12821270
    12831271    def test_basedir(self):
     
    12851273        # option after, or a basedir argument after, but none in the wrong
    12861274        # place, and not more than one of the three.
    1287         o = self.parse(["start"])
     1275
     1276        # Here is some option twistd recognizes but we don't.  Depending on
     1277        # where it appears, it should be passed through to twistd.  It doesn't
     1278        # really matter which option it is (it doesn't even have to be a valid
     1279        # option).  This test does not actually run any of the twistd argument
     1280        # parsing.
     1281        some_twistd_option = "--spew"
     1282
     1283        o = self.parse(["run"])
    12881284        self.failUnlessReallyEqual(o["basedir"], os.path.join(fileutil.abspath_expanduser_unicode(u"~"),
    12891285                                                              u".tahoe"))
    1290         o = self.parse(["start", "here"])
     1286        o = self.parse(["run", "here"])
    12911287        self.failUnlessReallyEqual(o["basedir"], fileutil.abspath_expanduser_unicode(u"here"))
    1292         o = self.parse(["start", "--basedir", "there"])
     1288        o = self.parse(["run", "--basedir", "there"])
    12931289        self.failUnlessReallyEqual(o["basedir"], fileutil.abspath_expanduser_unicode(u"there"))
    1294         o = self.parse(["--node-directory", "there", "start"])
     1290        o = self.parse(["--node-directory", "there", "run"])
    12951291        self.failUnlessReallyEqual(o["basedir"], fileutil.abspath_expanduser_unicode(u"there"))
    12961292
    1297         o = self.parse(["start", "here", "--nodaemon"])
     1293        o = self.parse(["run", "here", some_twistd_option])
    12981294        self.failUnlessReallyEqual(o["basedir"], fileutil.abspath_expanduser_unicode(u"here"))
    12991295
    13001296        self.failUnlessRaises(usage.UsageError, self.parse,
    1301                               ["--basedir", "there", "start"])
     1297                              ["--basedir", "there", "run"])
    13021298        self.failUnlessRaises(usage.UsageError, self.parse,
    1303                               ["start", "--node-directory", "there"])
     1299                              ["run", "--node-directory", "there"])
    13041300
    13051301        self.failUnlessRaises(usage.UsageError, self.parse,
    13061302                              ["--node-directory=there",
    1307                                "start", "--basedir=here"])
     1303                               "run", "--basedir=here"])
    13081304        self.failUnlessRaises(usage.UsageError, self.parse,
    1309                               ["start", "--basedir=here", "anywhere"])
     1305                              ["run", "--basedir=here", "anywhere"])
    13101306        self.failUnlessRaises(usage.UsageError, self.parse,
    13111307                              ["--node-directory=there",
    1312                                "start", "anywhere"])
     1308                               "run", "anywhere"])
    13131309        self.failUnlessRaises(usage.UsageError, self.parse,
    13141310                              ["--node-directory=there",
    1315                                "start", "--basedir=here", "anywhere"])
     1311                               "run", "--basedir=here", "anywhere"])
    13161312
    13171313        self.failUnlessRaises(usage.UsageError, self.parse,
    1318                               ["--node-directory=there", "start", "--nodaemon"])
     1314                              ["--node-directory=there", "run", some_twistd_option])
    13191315        self.failUnlessRaises(usage.UsageError, self.parse,
    1320                               ["start", "--basedir=here", "--nodaemon"])
    1321 
    1322 
    1323 class Stop(unittest.TestCase):
    1324     def test_non_numeric_pid(self):
    1325         """
    1326         If the pidfile exists but does not contain a numeric value, a complaint to
    1327         this effect is written to stderr and the non-success result is
    1328         returned.
    1329         """
    1330         basedir = FilePath(self.mktemp().decode("ascii"))
    1331         basedir.makedirs()
    1332         basedir.child(u"twistd.pid").setContent(b"foo")
    1333 
    1334         config = tahoe_stop.StopOptions()
    1335         config.stdout = StringIO()
    1336         config.stderr = StringIO()
    1337         config['basedir'] = basedir.path
    1338 
    1339         result_code = tahoe_stop.stop(config)
    1340         self.assertEqual(2, result_code)
    1341         self.assertIn("invalid PID file", config.stderr.getvalue())
    1342 
    1343 
    1344 class Start(unittest.TestCase):
    1345 
    1346     @patch('allmydata.scripts.run_common.os.chdir')
    1347     @patch('allmydata.scripts.run_common.twistd')
     1316                              ["run", "--basedir=here", some_twistd_option])
     1317
     1318
     1319class Run(unittest.TestCase):
     1320
     1321    @patch('allmydata.scripts.tahoe_run.os.chdir')
     1322    @patch('allmydata.scripts.tahoe_run.twistd')
    13481323    def test_non_numeric_pid(self, mock_twistd, chdir):
    13491324        """
     
    13561331        basedir.child(u"tahoe-client.tac").setContent(b"")
    13571332
    1358         config = tahoe_daemonize.DaemonizeOptions()
     1333        config = tahoe_run.RunOptions()
    13591334        config.stdout = StringIO()
    13601335        config.stderr = StringIO()
     
    13621337        config.twistd_args = []
    13631338
    1364         result_code = tahoe_daemonize.daemonize(config)
     1339        result_code = tahoe_run.run(config)
    13651340        self.assertIn("invalid PID file", config.stderr.getvalue())
    13661341        self.assertTrue(len(mock_twistd.mock_calls), 1)
  • TabularUnified src/allmydata/test/cli_node_api.py

    r052d95f r39628cb  
    66    "on_stdout_and_stderr",
    77    "on_different",
    8     "wait_for_exit",
    98]
    109
     
    1514import attr
    1615
     16from eliot import (
     17    log_call,
     18)
     19
    1720from twisted.internet.error import (
    18     ProcessDone,
    1921    ProcessTerminated,
    2022    ProcessExitedAlready,
     
    2527from twisted.python.filepath import (
    2628    FilePath,
    27 )
    28 from twisted.python.runtime import (
    29     platform,
    3029)
    3130from twisted.internet.protocol import (
     
    4342    _Client,
    4443)
    45 from ..scripts.tahoe_stop import (
    46     COULD_NOT_STOP,
    47 )
    4844from ..util.eliotutil import (
    4945    inline_callbacks,
     46    log_call_deferred,
    5047)
    5148
     
    157154        )
    158155
     156    @log_call(action_type="test:cli-api:run", include_args=["extra_tahoe_args"])
    159157    def run(self, protocol, extra_tahoe_args=()):
    160158        """
     
    177175                raise
    178176
    179     def stop(self, protocol):
    180         self._execute(
    181             protocol,
    182             [u"stop", self.basedir.asTextMode().path],
    183         )
    184 
     177    @log_call_deferred(action_type="test:cli-api:stop")
     178    def stop(self):
     179        return self.stop_and_wait()
     180
     181    @log_call_deferred(action_type="test:cli-api:stop-and-wait")
    185182    @inline_callbacks
    186183    def stop_and_wait(self):
    187         if platform.isWindows():
    188             # On Windows there is no PID file and no "tahoe stop".
    189             if self.process is not None:
    190                 while True:
    191                     try:
    192                         self.process.signalProcess("TERM")
    193                     except ProcessExitedAlready:
    194                         break
    195                     else:
    196                         yield deferLater(self.reactor, 0.1, lambda: None)
    197         else:
    198             protocol, ended = wait_for_exit()
    199             self.stop(protocol)
    200             yield ended
     184        if self.process is not None:
     185            while True:
     186                try:
     187                    self.process.signalProcess("TERM")
     188                except ProcessExitedAlready:
     189                    break
     190                else:
     191                    yield deferLater(self.reactor, 0.1, lambda: None)
    201192
    202193    def active(self):
     
    209200        # Let it fail because the process has already exited.
    210201        reason.trap(ProcessTerminated)
    211         if reason.value.exitCode != COULD_NOT_STOP:
    212             return reason
    213202        return None
    214203
     
    217206        stopping.addErrback(self._check_cleanup_reason)
    218207        return stopping
    219 
    220 
    221 class _WaitForEnd(ProcessProtocol, object):
    222     def __init__(self, ended):
    223         self._ended = ended
    224 
    225     def processEnded(self, reason):
    226         if reason.check(ProcessDone):
    227             self._ended.callback(None)
    228         else:
    229             self._ended.errback(reason)
    230 
    231 
    232 def wait_for_exit():
    233     ended = Deferred()
    234     protocol = _WaitForEnd(ended)
    235     return protocol, ended
  • TabularUnified src/allmydata/test/test_runner.py

    r052d95f r39628cb  
    3535from ..util.eliotutil import (
    3636    inline_callbacks,
     37    log_call_deferred,
    3738)
    3839
     
    5556
    5657class RunBinTahoeMixin(object):
     58    @log_call_deferred(action_type="run-bin-tahoe")
    5759    def run_bintahoe(self, args, stdin=None, python_options=[], env=None):
    5860        command = sys.executable
     
    143145
    144146class CreateNode(unittest.TestCase):
    145     # exercise "tahoe create-node", create-introducer, and
    146     # create-key-generator by calling the corresponding code as a subroutine.
     147    # exercise "tahoe create-node" and "tahoe create-introducer" by calling
     148    # the corresponding code as a subroutine.
    147149
    148150    def workdir(self, name):
     
    252254              RunBinTahoeMixin):
    253255    """
    254     exercise "tahoe run" for both introducer, client node, and key-generator,
    255     by spawning "tahoe run" (or "tahoe start") as a subprocess. This doesn't
    256     get us line-level coverage, but it does a better job of confirming that
    257     the user can actually run "./bin/tahoe run" and expect it to work. This
    258     verifies that bin/tahoe sets up PYTHONPATH and the like correctly.
    259 
    260     This doesn't work on cygwin (it hangs forever), so we skip this test
    261     when we're on cygwin. It is likely that "tahoe start" itself doesn't
    262     work on cygwin: twisted seems unable to provide a version of
    263     spawnProcess which really works there.
     256    exercise "tahoe run" for both introducer and client node, by spawning
     257    "tahoe run" as a subprocess. This doesn't get us line-level coverage, but
     258    it does a better job of confirming that the user can actually run
     259    "./bin/tahoe run" and expect it to work. This verifies that bin/tahoe sets
     260    up PYTHONPATH and the like correctly.
    264261    """
    265262
     
    341338    def test_client(self):
    342339        """
    343         Test many things.
     340        Test too many things.
    344341
    345342        0) Verify that "tahoe create-node" takes a --webport option and writes
     
    349346
    350347        2) Verify that the storage furl file has a stable value across a
    351            "tahoe run" / "tahoe stop" / "tahoe run" sequence.
    352 
    353         3) Verify that the pid file is removed after "tahoe stop" succeeds (on POSIX).
     348           "tahoe run" / stop / "tahoe run" sequence.
     349
     350        3) Verify that the pid file is removed after SIGTERM (on POSIX).
    354351        """
    355352        basedir = self.workdir("test_client")
     
    455452        )
    456453
    457     def test_stop_bad_directory(self):
    458         """
    459         If ``tahoe run`` is pointed at a directory where no node is running, it
    460         reports an error and exits.
    461         """
    462         return self._bad_directory_test(
    463             u"test_stop_bad_directory",
    464             "tahoe stop",
    465             lambda tahoe, p: tahoe.stop(p),
    466             "does not look like a running node directory",
    467         )
    468 
    469454    @inline_callbacks
    470455    def _bad_directory_test(self, workdir, description, operation, expected_message):
Note: See TracChangeset for help on using the changeset viewer.