make provisioning/reliability work in the new location, fix tests

This commit is contained in:
Brian Warner 2012-02-15 18:24:42 +00:00
parent 11f9394704
commit fe1df149e1
7 changed files with 257 additions and 18 deletions

@ -199,6 +199,10 @@ check-grid: .built
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:

@ -1,12 +1,17 @@
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
@ -35,7 +40,7 @@ def binomial(n, k):
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)
@ -566,12 +571,12 @@ class ProvisioningTool(rend.Page):
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])
@ -606,8 +611,7 @@ class ProvisioningTool(rend.Page):
# $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])

@ -0,0 +1,45 @@
#!/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)

@ -0,0 +1,163 @@
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
}

@ -1,5 +1,5 @@
from twisted.trial import unittest
import unittest
from allmydata import provisioning
ReliabilityModel = None
try:
@ -111,3 +111,5 @@ class Reliability(unittest.TestCase):
self.failUnlessAlmostEqual(P_dead_unmaintained, 0.033591004555395272)
self.failUnlessAlmostEqual(P_dead_maintained, 3.2983995819177542e-08)
if __name__=='__main__':
unittest.main()

@ -0,0 +1,5 @@
import os.path
def sibling(filename):
return os.path.join(os.path.dirname(os.path.abspath(__file__)), filename)

@ -1,11 +1,27 @@
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
@ -22,7 +38,7 @@ def yandm(seconds):
class ReliabilityTool(rend.Page):
addSlash = True
docFactory = getxmlfile("reliability.xhtml")
docFactory = loaders.xmlfile(util.sibling("reliability.xhtml"))
DEFAULT_PARAMETERS = [
("drive_lifetime", "8Y", "time",