bench-dirnode: .built
$(TAHOE) @src/allmydata/test/bench_dirnode.py
+# the provisioning tool runs as a stand-alone webapp server
+run-provisioning-tool: .built
+ $(TAHOE) @misc/operations_helpers/provisioning/run.py
+
# 'make repl' is a simple-to-type command to get a Python interpreter loop
# from which you can type 'import allmydata'
repl:
-from nevow import inevow, rend, tags as T
+from nevow import inevow, rend, loaders, tags as T
import math
-from allmydata.util import mathutil
-from allmydata.web.common import getxmlfile
+import util
# factorial and binomial copied from
# http://mail.python.org/pipermail/python-list/2007-April/435718.html
+def div_ceil(n, d):
+ """
+ The smallest integer k such that k*d >= n.
+ """
+ return (n/d) + (n%d != 0)
+
def factorial(n):
"""factorial(n): return the factorial of the integer n.
factorial(0) = 1
class ProvisioningTool(rend.Page):
addSlash = True
- docFactory = getxmlfile("provisioning.xhtml")
+ docFactory = loaders.xmlfile(util.sibling("provisioning.xhtml"))
def render_forms(self, ctx, data):
req = inevow.IRequest(ctx)
number(total_file_check_rate,
"Hz")])
- total_drives = max(mathutil.div_ceil(int(total_share_space),
- int(drive_size)),
+ total_drives = max(div_ceil(int(total_share_space),
+ int(drive_size)),
num_servers)
add_output("Drives",
T.div["Total drives: ", number(total_drives), " drives"])
- drives_per_server = mathutil.div_ceil(total_drives, num_servers)
+ drives_per_server = div_ceil(total_drives, num_servers)
add_output("Servers",
T.div["Drives per server: ", drives_per_server])
# $44/server/mo power+space
server_bandwidth = max(server_inbound_byte_rate,
server_outbound_byte_rate)
- server_bandwidth_mbps = mathutil.div_ceil(int(server_bandwidth*8),
- int(1e6))
+ server_bandwidth_mbps = div_ceil(int(server_bandwidth*8), int(1e6))
server_monthly_cost = 70*server_bandwidth_mbps + 44
add_output("Servers", T.div["Monthly cost per server: $",
server_monthly_cost])
--- /dev/null
+#!/usr/bin/env python
+
+# this depends upon Twisted and Nevow, but not upon Tahoe itself
+
+import webbrowser
+
+from twisted.application import strports
+from twisted.internet import reactor
+from nevow import appserver, rend, loaders
+from twisted.web import static
+import web_reliability, provisioning
+
+class Root(rend.Page):
+ docFactory = loaders.xmlstr('''\
+<html xmlns:n="http://nevow.com/ns/nevow/0.1">
+ <head>
+ <title>Tahoe-LAFS Provisioning/Reliability Calculator</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ </head>
+ <body>
+ <p><a href="reliability">Reliability Tool</a></p>
+ <p><a href="provisioning">Provisioning Tool</a></p>
+ </body>
+</html>
+''')
+
+ child_reliability = web_reliability.ReliabilityTool()
+ child_provisioning = provisioning.ProvisioningTool()
+
+
+def run(portnum):
+ root = Root()
+ root.putChild("tahoe.css", static.File("tahoe.css"))
+ site = appserver.NevowSite(root)
+ s = strports.service("tcp:%d" % portnum, site)
+ s.startService()
+ reactor.callLater(1.0, webbrowser.open, "http://localhost:%d/" % portnum)
+ reactor.run()
+
+if __name__ == '__main__':
+ import sys
+ portnum = 8070
+ if len(sys.argv) > 1:
+ portnum = int(sys.argv[1])
+ run(portnum)
--- /dev/null
+
+pre.overflow {
+ background: #f7f7f7;
+ border: 1px solid #d7d7d7;
+ margin: 1em 1.75em;
+ padding: .25em;
+ overflow: auto;
+ }
+
+/* ----------------------------------------------------------------------- */
+
+/* colors borrowed from the Allmydata logo */
+
+/* general style */
+h1 {
+ text-align: center;
+}
+table {
+ margin: 1em auto;
+ border: .2em solid #3289b4;
+ border-spacing: 1px;
+}
+th {
+ color: white;
+ background-color: #58a1c3;
+}
+td {
+ padding: .3em .3em;
+}
+
+th {
+ padding: .3em .3em;
+}
+
+.table-headings-top th {
+ text-align: center;
+
+}
+.table-headings-left th {
+ text-align: right;
+ vertical-align: top;
+}
+legend {
+ font-weight: bold;
+}
+
+.connected-yes, .connected-True {
+ border: 1px solid #75d24a;
+ background-color: #EFE;
+}
+.connected-no, .connected-False {
+ border: 1px solid #F00;
+ background-color: #FBB;
+}
+
+.encoded, .nodeid {
+ font-family: monospace;
+ font-size: 80%;
+}
+
+.empty-marker {
+ background-color: white;
+ color: gray;
+}
+table td.empty-marker {
+ padding: 6em 10em;
+ text-align: center;
+ vertical-align: center;
+}
+
+/* styles for server listings in tables (nickname above nodeid) */
+th.nickname-and-peerid {
+ text-align: left;
+}
+.nickname {
+ font: inherit;
+ font-family: sans-serif;
+ font-weight: bold;
+}
+
+
+/* just in case, make sure floats don't stomp on big tables etc. */
+#section { clear: both; }
+
+/* section-specific styles - turn this client info into a sidebar */
+#this-client {
+ font-size: 60%;
+ border: .2em solid #3289b4;
+ float: right;
+ width: 40%;
+ margin: 0 0 .5em .5em;
+ padding: 3px;
+}
+#this-client .nodeid { font-size: inherit; }
+#this-client h2 {
+ text-align: center;
+ background: #3289b4;
+ color: white;
+ margin: -2px -2px 0 -2px; /* matches padding */
+ padding: .3em;
+}
+#this-client table {
+ font-size: inherit;
+ margin: 0 -3px -3px -3px; /* matches padding */
+}
+#this-client td > ul {
+ list-style-type: outside;
+ margin: 0 0 0 2.3em;
+ padding-left: 0;
+}
+
+
+/* services table */
+.services {
+}
+
+/* --- Directory page styles --- */
+
+body.tahoe-directory-page {
+ color: black;
+ background: #c0d9e6;
+ margin: 1em 0; /* zero margin so the table can be flush */
+}
+table.tahoe-directory {
+ color: black;
+ background: white;
+ width: 100%;
+ /*border-left-color: #D7E0E5;
+ border-right-color: #D7E0E5;*/
+ border-left: 0;
+ border-right: 0;
+}
+.tahoe-directory-footer {
+ color: black;
+ background: #c0d9e6;
+ margin: 0 1em; /* compensate for page 0 margin */
+}
+
+/* directory-screen toolbar */
+.toolbar {
+ display: table;
+ margin: .2em auto;
+ text-align: center;
+ /*width: 100%;*/
+}
+.toolbar .toolbar-item {
+ display: inline;
+ text-align: center;
+ padding: 0 1em;
+}
+
+/* recent upload/download status pages */
+
+table.status-download-events {
+ #border: 1px solid #aaa;
+ margin: 1em auto;
+ border: .2em solid #3289b4;
+ border-spacing: 1px;
+}
+table.status-download-events td {
+ border: 1px solid #a00;
+ padding: 2px
+}
-from twisted.trial import unittest
+import unittest
from allmydata import provisioning
ReliabilityModel = None
try:
self.failUnlessAlmostEqual(P_dead_unmaintained, 0.033591004555395272)
self.failUnlessAlmostEqual(P_dead_maintained, 3.2983995819177542e-08)
+if __name__=='__main__':
+ unittest.main()
--- /dev/null
+
+import os.path
+
+def sibling(filename):
+ return os.path.join(os.path.dirname(os.path.abspath(__file__)), filename)
-from nevow import rend, tags as T
-reliability = None # might not be usable
-try:
- from allmydata import reliability # requires NumPy
-except ImportError:
- pass
-from allmydata.web.common import getxmlfile, get_arg
+from nevow import rend, loaders, tags as T
+from nevow.inevow import IRequest
+import reliability # requires NumPy
+import util
+
+def get_arg(ctx_or_req, argname, default=None, multiple=False):
+ """Extract an argument from either the query args (req.args) or the form
+ body fields (req.fields). If multiple=False, this returns a single value
+ (or the default, which defaults to None), and the query args take
+ precedence. If multiple=True, this returns a tuple of arguments (possibly
+ empty), starting with all those in the query args.
+ """
+ req = IRequest(ctx_or_req)
+ results = []
+ if argname in req.args:
+ results.extend(req.args[argname])
+ if req.fields and argname in req.fields:
+ results.append(req.fields[argname].value)
+ if multiple:
+ return tuple(results)
+ if results:
+ return results[0]
+ return default
DAY=24*60*60
class ReliabilityTool(rend.Page):
addSlash = True
- docFactory = getxmlfile("reliability.xhtml")
+ docFactory = loaders.xmlfile(util.sibling("reliability.xhtml"))
DEFAULT_PARAMETERS = [
("drive_lifetime", "8Y", "time",