This file is indexed.

/usr/share/munin/plugins/tahoe_spacetime is in tahoe-lafs 1.9.2-1.

This file is owned by root:root, with mode 0o755.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
#!/usr/bin/env python

# copy .rrd files from a remote munin master host, sum the 'df' stats from a
# list of hosts, use them to estimate a rate-of-change for the past month,
# then extrapolate to guess how many weeks/months/years of storage space we
# have left, and output it to another munin graph

import sys, os, time
import rrdtool

MUNIN_HOST = "munin.allmydata.com"
PREFIX = "%s:/var/lib/munin/prodtahoe/" % MUNIN_HOST
FILES = [ "prodtahoe%d.allmydata.com-df-_dev_sd%s3-g.rrd" % (a,b)
          for a in (1,2,3,4,5)
          for b in ("a", "b", "c", "d")
          ]
REMOTEFILES = [ PREFIX + f for f in FILES ]
LOCALFILES = ["/var/lib/munin/prodtahoe/" + f for f in FILES ]
WEBFILE = "/var/www/tahoe/spacetime.json"


def rsync_rrd():
    # copy the RRD files from your munin master host to a local one
    cmd = "rsync %s rrds/" % (" ".join(REMOTEFILES))
    rc = os.system(cmd)
    assert rc == 0, rc

def format_time(t):
    return time.strftime("%b %d %H:%M", time.localtime(t))

def predict_future(past_s):

    start_df = []
    end_df = []
    durations = []

    for fn in LOCALFILES:
        d = rrdtool.fetch(fn, "AVERAGE", "-s", "-"+past_s, "-e", "-1hr")
        # ((start, end, step), (name1, name2, ...), [(data1, data2, ..), ...])
        (start_time, end_time ,step) = d[0]
        #print format_time(start_time), " - ", format_time(end_time), step
        names = d[1]
        #for points in d[2]:
        #    point = points[0]
        #    print point
        start_space = d[2][0][0]
        if start_space is None:
            return None
        # I don't know why, but the last few points are always bogus. Running
        # 'rrdtool fetch' on the command line is usually ok.. I blame the python
        # bindinds.
        end_space = d[2][-4][0]
        if end_space is None:
            return None
        end_time = end_time - (4*step)
        start_df.append(start_space)
        end_df.append(end_space)
        durations.append(end_time - start_time)

    avg_start_df = sum(start_df) / len(start_df)
    avg_end_df = sum(end_df) / len(end_df)
    avg_duration = sum(durations) / len(durations)
    #print avg_start_df, avg_end_df, avg_duration

    rate = (avg_end_df - avg_start_df) / avg_duration
    #print "Rate", rate, " %/s"
    #print "measured over", avg_duration / 86400, "days"
    remaining = 100 - avg_end_df
    remaining_seconds = remaining / rate
    #print "remaining seconds", remaining_seconds
    remaining_days = remaining_seconds / 86400
    #print "remaining days", remaining_days
    return remaining_days

def write_to_file(samples):
    # write a JSON-formatted dictionary
    f = open(WEBFILE + ".tmp", "w")
    f.write("{ ")
    f.write(", ".join(['"%s": %s' % (k, samples[k])
                       for k in sorted(samples.keys())]))
    f.write("}\n")
    f.close()
    os.rename(WEBFILE + ".tmp", WEBFILE)

if len(sys.argv) > 1 and sys.argv[1] == "config":
    print """\
graph_title Tahoe Remaining Space Predictor
graph_vlabel days remaining
graph_category tahoe
graph_info This graph shows the estimated number of days left until storage space is exhausted
days_2wk.label days left (2wk sample)
days_2wk.draw LINE2
days_4wk.label days left (4wk sample)
days_4wk.draw LINE2"""
    sys.exit(0)

#rsync_rrd()
samples = {}
remaining_4wk = predict_future("4wk")
if remaining_4wk is not None:
    print "days_4wk.value", remaining_4wk
    samples["remaining_4wk"] = remaining_4wk
remaining_2wk = predict_future("2wk")
if remaining_2wk is not None:
    print "days_2wk.value", remaining_2wk
    samples["remaining_2wk"] = remaining_2wk
write_to_file(samples)