Changeset f57d1e9 in trunk


Ignore:
Timestamp:
2016-05-05T01:37:23Z (9 years ago)
Author:
Brian Warner <warner@…>
Branches:
master
Children:
1e1e86f
Parents:
d1d9884 (diff), 93bb3e9 (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.
Message:

Merge branch '2773-stats'

This changes "tahoe create-stats-gatherer" to take --hostname,
--location, and --port, according to (refs ticket:2773).

Files:
1 added
5 edited

Legend:

Unmodified
Added
Removed
  • TabularUnified docs/stats.rst

    rd1d9884 rf57d1e9  
    280280The stats-gatherer is created in the same fashion as regular tahoe client
    281281nodes and introducer nodes. Choose a base directory for the gatherer to live
    282 in (but do not create the directory). Then run:
     282in (but do not create the directory). Choose the hostname that should be
     283advertised in the gatherer's FURL. Then run:
    283284
    284285::
    285286
    286    tahoe create-stats-gatherer $BASEDIR
     287   tahoe create-stats-gatherer --hostname=HOSTNAME $BASEDIR
    287288
    288289and start it with "tahoe start $BASEDIR". Once running, the gatherer will
     
    296297
    297298    [client]
    298     stats_gatherer.furl = pb://qbo4ktl667zmtiuou6lwbjryli2brv6t@192.168.0.8:49997/wxycb4kaexzskubjnauxeoptympyf45y
     299    stats_gatherer.furl = pb://qbo4ktl667zmtiuou6lwbjryli2brv6t@HOSTNAME:PORTNUM/wxycb4kaexzskubjnauxeoptympyf45y
    299300
    300301or simply copy the stats_gatherer.furl file into the node's base directory
    301302(next to the tahoe.cfg file): it will be interpreted in the same way.
    302303
    303 The first time it is started, the gatherer will listen on a random unused TCP
    304 port, so it should not conflict with anything else that you have running on
    305 that host at that time. On subsequent runs, it will re-use the same port (to
    306 keep its FURL consistent). To explicitly control which port it uses, write
    307 the desired portnumber into a file named "portnum" (i.e. $BASEDIR/portnum),
    308 and the next time the gatherer is started, it will start listening on the
    309 given port. The portnum file is actually a "strports specification string",
    310 as described in :doc:`configuration`.
     304When the gatherer is created, it will allocate a random unused TCP port, so
     305it should not conflict with anything else that you have running on that host
     306at that time. To explicitly control which port it uses, run the creation
     307command with ``--location=`` and ``--port=`` instead of ``--hostname=``. If
     308you use a hostname of ``example.org`` and a port number of ``1234``, then
     309run::
     310
     311  tahoe create-stats-gatherer --location=tcp:example.org:1234 --port=tcp:1234
     312
     313``--location=`` is a Foolscap FURL hints string (so it can be a
     314comma-separated list of connection hints), and ``--port=`` is a Twisted
     315"server endpoint specification string", as described in :doc:`configuration`.
    311316
    312317Once running, the stats gatherer will create a standard JSON file in
     
    323328"storage_server.disk_avail' values from all servers to compute a
    324329total-disk-available number for the entire grid (however, the "disk watcher"
    325 daemon, in misc/operations_helpers/spacetime/, is better suited for this specific task).
     330daemon, in misc/operations_helpers/spacetime/, is better suited for this
     331specific task).
    326332
    327333Using Munin To Graph Stats Values
    328334=================================
    329335
    330 The misc/munin/ directory contains various plugins to graph stats for Tahoe
    331 nodes. They are intended for use with the Munin_ system-management tool, which
    332 typically polls target systems every 5 minutes and produces a web page with
    333 graphs of various things over multiple time scales (last hour, last month,
    334 last year).
     336The misc/operations_helpers/munin/ directory contains various plugins to
     337graph stats for Tahoe nodes. They are intended for use with the Munin_
     338system-management tool, which typically polls target systems every 5 minutes
     339and produces a web page with graphs of various things over multiple time
     340scales (last hour, last month, last year).
    335341
    336342Most of the plugins are designed to pull stats from a single Tahoe node, and
  • TabularUnified src/allmydata/scripts/stats_gatherer.py

    rd1d9884 rf57d1e9  
    1 
    21import os, sys
    3 
     2from twisted.python import usage
    43from allmydata.scripts.common import NoDefaultBasedirOptions
    54from allmydata.scripts.create_node import write_tac
    65from allmydata.util.assertutil import precondition
    76from allmydata.util.encodingutil import listdir_unicode, quote_output
     7from allmydata.util import fileutil, iputil
    88
    99
    1010class CreateStatsGathererOptions(NoDefaultBasedirOptions):
    1111    subcommand_name = "create-stats-gatherer"
     12    optParameters = [
     13        ("hostname", None, None, "Hostname of this machine, used to build location"),
     14        ("location", None, None, "FURL connection hints, e.g. 'tcp:HOSTNAME:PORT'"),
     15        ("port", None, None, "listening endpoint, e.g. 'tcp:PORT'"),
     16        ]
     17    def postOptions(self):
     18        if self["hostname"] and (not self["location"]) and (not self["port"]):
     19            pass
     20        elif (not self["hostname"]) and self["location"] and self["port"]:
     21            pass
     22        else:
     23            raise usage.UsageError("You must provide --hostname, or --location and --port.")
     24
     25    description = """
     26    Create a "stats-gatherer" service, which is a standalone process that
     27    collects and stores runtime statistics from many server nodes. This is a
     28    tool for operations personnel to keep track of free disk space, server
     29    load, and protocol activity, across a fleet of Tahoe storage servers.
     30
     31    The "stats-gatherer" listens on a TCP port and publishes a Foolscap FURL
     32    by writing it into a file named "stats_gatherer.furl". You must copy this
     33    FURL into the servers' tahoe.cfg, as the [client] stats_gatherer.furl=
     34    entry. Those servers will then establish a connection to the
     35    stats-gatherer and publish their statistics on a periodic basis. The
     36    gatherer writes a summary JSON file out to disk after each update.
     37
     38    The stats-gatherer listens on a configurable port, and writes a
     39    configurable hostname+port pair into the FURL that it publishes. There
     40    are two configuration modes you can use.
     41
     42    * In the first, you provide --hostname=, and the service chooses its own
     43      TCP port number. If the host is named "example.org" and you provide
     44      --hostname=example.org, the node will pick a port number (e.g. 12345)
     45      and use location="tcp:example.org:12345" and port="tcp:12345".
     46
     47    * In the second, you provide both --location= and --port=, and the
     48      service will refrain from doing any allocation of its own. --location=
     49      must be a Foolscap "FURL connection hint sequence", which is a
     50      comma-separated list of "tcp:HOSTNAME:PORTNUM" strings. --port= must be
     51      a Twisted server endpoint specification, which is generally
     52      "tcp:PORTNUM". So, if your host is named "example.org" and you want to
     53      use port 6789, you should provide --location=tcp:example.org:6789 and
     54      --port=tcp:6789. You are responsible for making sure --location= and
     55      --port= match each other.
     56    """
    1257
    1358
     
    2772        os.mkdir(basedir)
    2873    write_tac(basedir, "stats-gatherer")
     74    if config["hostname"]:
     75        portnum = iputil.allocate_tcp_port()
     76        location = "tcp:%s:%d" % (config["hostname"], portnum)
     77        port = "tcp:%d" % portnum
     78    else:
     79        location = config["location"]
     80        port = config["port"]
     81    fileutil.write(os.path.join(basedir, "location"), location+"\n")
     82    fileutil.write(os.path.join(basedir, "port"), port+"\n")
    2983    return 0
    3084
  • TabularUnified src/allmydata/stats.py

    rd1d9884 rf57d1e9  
    1212from foolscap.api import eventually, DeadReferenceError, Referenceable, Tub
    1313
    14 from allmydata.util import log, fileutil
     14from allmydata.util import log
    1515from allmydata.util.encodingutil import quote_local_unicode_path
    1616from allmydata.interfaces import RIStatsProvider, RIStatsGatherer, IStatsProducer
     
    295295        self.stats_gatherer.setServiceParent(self)
    296296
    297         portnumfile = os.path.join(self.basedir, "portnum")
    298297        try:
    299             portnum = open(portnumfile, "r").read()
     298            with open(os.path.join(self.basedir, "location")) as f:
     299                location = f.read().strip()
    300300        except EnvironmentError:
    301             portnum = None
    302         self.listener = self.tub.listenOn(portnum or "tcp:0")
    303         d = self.tub.setLocationAutomatically()
    304         if portnum is None:
    305             d.addCallback(self.save_portnum)
    306         d.addCallback(self.tub_ready)
    307         d.addErrback(log.err)
    308 
    309     def save_portnum(self, junk):
    310         portnum = self.listener.getPortnum()
    311         portnumfile = os.path.join(self.basedir, 'portnum')
    312         fileutil.write(portnumfile, '%d\n' % (portnum,))
    313 
    314     def tub_ready(self, ignored):
     301            raise ValueError("Unable to find 'location' in BASEDIR, please rebuild your stats-gatherer")
     302        try:
     303            with open(os.path.join(self.basedir, "port")) as f:
     304                port = f.read().strip()
     305        except EnvironmentError:
     306            raise ValueError("Unable to find 'port' in BASEDIR, please rebuild your stats-gatherer")
     307
     308        self.tub.listenOn(port)
     309        self.tub.setLocation(location)
    315310        ff = os.path.join(self.basedir, self.furl_file)
    316311        self.gatherer_furl = self.tub.registerReference(self.stats_gatherer,
  • TabularUnified src/allmydata/test/common.py

    rd1d9884 rf57d1e9  
    495495        statsdir = self.getdir("stats_gatherer")
    496496        fileutil.make_dirs(statsdir)
     497        portnum = iputil.allocate_tcp_port()
     498        location = "tcp:127.0.0.1:%d" % portnum
     499        fileutil.write(os.path.join(statsdir, "location"), location)
     500        port = "tcp:%d:interface=127.0.0.1" % portnum
     501        fileutil.write(os.path.join(statsdir, "port"), port)
    497502        self.stats_gatherer_svc = StatsGathererService(statsdir)
    498503        self.stats_gatherer = self.stats_gatherer_svc.stats_gatherer
  • TabularUnified src/allmydata/test/test_runner.py

    rd1d9884 rf57d1e9  
    185185        return rc, out.getvalue(), err.getvalue()
    186186
    187     def do_create(self, kind):
     187    def do_create(self, kind, *args):
    188188        basedir = self.workdir("test_" + kind)
    189189        command = "create-" + kind
     
    192192
    193193        n1 = os.path.join(basedir, command + "-n1")
    194         argv = ["--quiet", command, "--basedir", n1]
     194        argv = ["--quiet", command, "--basedir", n1] + list(args)
    195195        rc, out, err = self.run_tahoe(argv)
    196196        self.failUnlessEqual(err, "")
     
    227227        # test that the non --basedir form works too
    228228        n2 = os.path.join(basedir, command + "-n2")
    229         argv = ["--quiet", command, n2]
     229        argv = ["--quiet", command] + list(args) + [n2]
    230230        rc, out, err = self.run_tahoe(argv)
    231231        self.failUnlessEqual(err, "")
     
    237237        # test the --node-directory form
    238238        n3 = os.path.join(basedir, command + "-n3")
    239         argv = ["--quiet", "--node-directory", n3, command]
     239        argv = ["--quiet", "--node-directory", n3, command] + list(args)
    240240        rc, out, err = self.run_tahoe(argv)
    241241        self.failUnlessEqual(err, "")
     
    248248            # test that the output (without --quiet) includes the base directory
    249249            n4 = os.path.join(basedir, command + "-n4")
    250             argv = [command, n4]
     250            argv = [command] + list(args) + [n4]
    251251            rc, out, err = self.run_tahoe(argv)
    252252            self.failUnlessEqual(err, "")
     
    283283
    284284    def test_stats_gatherer(self):
    285         self.do_create("stats-gatherer")
     285        self.do_create("stats-gatherer", "--hostname=127.0.0.1")
    286286
    287287    def test_subcommands(self):
     
    292292                              run_by_human=False)
    293293
     294    def test_stats_gatherer_good_args(self):
     295        rc = runner.runner(["create-stats-gatherer", "--hostname=foo",
     296                            self.mktemp()])
     297        self.assertEqual(rc, 0)
     298        rc = runner.runner(["create-stats-gatherer", "--location=tcp:foo:1234",
     299                            "--port=tcp:1234", self.mktemp()])
     300        self.assertEqual(rc, 0)
     301
     302    def test_stats_gatherer_bad_args(self):
     303        # missing hostname/location/port
     304        argv = "create-stats-gatherer D"
     305        self.assertRaises(usage.UsageError, runner.runner, argv.split(),
     306                          run_by_human=False)
     307
     308        # missing port
     309        argv = "create-stats-gatherer --location=foo D"
     310        self.assertRaises(usage.UsageError, runner.runner, argv.split(),
     311                          run_by_human=False)
     312
     313        # missing location
     314        argv = "create-stats-gatherer --port=foo D"
     315        self.assertRaises(usage.UsageError, runner.runner, argv.split(),
     316                          run_by_human=False)
     317
     318        # can't provide both
     319        argv = "create-stats-gatherer --hostname=foo --port=foo D"
     320        self.assertRaises(usage.UsageError, runner.runner, argv.split(),
     321                          run_by_human=False)
     322
     323        # can't provide both
     324        argv = "create-stats-gatherer --hostname=foo --location=foo D"
     325        self.assertRaises(usage.UsageError, runner.runner, argv.split(),
     326                          run_by_human=False)
     327
     328        # can't provide all three
     329        argv = "create-stats-gatherer --hostname=foo --location=foo --port=foo D"
     330        self.assertRaises(usage.UsageError, runner.runner, argv.split(),
     331                          run_by_human=False)
    294332
    295333class RunNode(common_util.SignalMixin, unittest.TestCase, pollmixin.PollMixin,
Note: See TracChangeset for help on using the changeset viewer.