2008-07-16 22:42:56 +00:00
|
|
|
|
2008-08-13 03:34:26 +00:00
|
|
|
import time
|
2008-07-16 22:42:56 +00:00
|
|
|
from nevow import rend, inevow, tags as T
|
2008-09-07 19:44:56 +00:00
|
|
|
from twisted.web import html
|
|
|
|
from allmydata.web.common import getxmlfile, get_arg, IClient
|
|
|
|
from allmydata.interfaces import ICheckAndRepairResults, ICheckerResults, \
|
|
|
|
IDeepCheckResults, IDeepCheckAndRepairResults
|
|
|
|
from allmydata.util import base32, idlib
|
2008-07-16 22:42:56 +00:00
|
|
|
|
2008-09-07 19:44:56 +00:00
|
|
|
class ResultsBase:
|
|
|
|
def _render_results(self, cr):
|
|
|
|
assert ICheckerResults(cr)
|
|
|
|
return T.pre["\n".join(self._html(cr.get_report()))] # TODO: more
|
|
|
|
def _html(self, s):
|
|
|
|
if isinstance(s, (str, unicode)):
|
|
|
|
return html.escape(s)
|
|
|
|
assert isinstance(s, (list, tuple))
|
|
|
|
return [html.escape(w) for w in s]
|
|
|
|
|
|
|
|
class CheckerResults(rend.Page, ResultsBase):
|
2008-07-16 22:42:56 +00:00
|
|
|
docFactory = getxmlfile("checker-results.xhtml")
|
|
|
|
|
|
|
|
def __init__(self, results):
|
2008-09-07 19:44:56 +00:00
|
|
|
self.r = ICheckerResults(results)
|
2008-07-16 22:42:56 +00:00
|
|
|
|
|
|
|
def render_storage_index(self, ctx, data):
|
|
|
|
return self.r.get_storage_index_string()
|
|
|
|
|
2008-09-07 19:44:56 +00:00
|
|
|
def render_healthy(self, ctx, data):
|
|
|
|
if self.r.is_healthy():
|
|
|
|
return ctx.tag["Healthy!"]
|
|
|
|
return ctx.tag["Not Healthy!:", self._html(self.r.get_summary())]
|
2008-07-16 22:42:56 +00:00
|
|
|
|
|
|
|
def render_results(self, ctx, data):
|
2008-09-07 19:44:56 +00:00
|
|
|
cr = self._render_results(self.r)
|
|
|
|
return ctx.tag[cr]
|
2008-07-16 22:42:56 +00:00
|
|
|
|
|
|
|
def render_return(self, ctx, data):
|
|
|
|
req = inevow.IRequest(ctx)
|
|
|
|
return_to = get_arg(req, "return_to", None)
|
|
|
|
if return_to:
|
|
|
|
return T.div[T.a(href=return_to)["Return to parent directory"]]
|
|
|
|
return ""
|
2008-07-17 23:47:09 +00:00
|
|
|
|
2008-09-07 19:44:56 +00:00
|
|
|
class CheckAndRepairResults(rend.Page, ResultsBase):
|
|
|
|
docFactory = getxmlfile("check-and-repair-results.xhtml")
|
|
|
|
|
|
|
|
def __init__(self, results):
|
|
|
|
self.r = ICheckAndRepairResults(results)
|
|
|
|
|
|
|
|
def render_storage_index(self, ctx, data):
|
|
|
|
return self.r.get_storage_index_string()
|
|
|
|
|
|
|
|
def render_healthy(self, ctx, data):
|
|
|
|
cr = self.r.get_post_repair_results()
|
|
|
|
if cr.is_healthy():
|
|
|
|
return ctx.tag["Healthy!"]
|
|
|
|
return ctx.tag["Not Healthy!:", self._html(cr.get_summary())]
|
|
|
|
|
|
|
|
def render_repair_results(self, ctx, data):
|
|
|
|
if self.r.get_repair_attempted():
|
|
|
|
if self.r.get_repair_successful():
|
|
|
|
return ctx.tag["Repair successful"]
|
|
|
|
else:
|
|
|
|
return ctx.tag["Repair unsuccessful"]
|
|
|
|
return ctx.tag["No repair necessary"]
|
|
|
|
|
|
|
|
def render_post_repair_results(self, ctx, data):
|
|
|
|
cr = self._render_results(self.r.get_post_repair_results())
|
|
|
|
return ctx.tag[cr]
|
|
|
|
|
|
|
|
def render_maybe_pre_repair_results(self, ctx, data):
|
|
|
|
if self.r.get_repair_attempted():
|
|
|
|
cr = self._render_results(self.r.get_pre_repair_results())
|
|
|
|
return ctx.tag[T.div["Pre-Repair Checker Results:"], cr]
|
|
|
|
return ""
|
|
|
|
|
|
|
|
def render_return(self, ctx, data):
|
|
|
|
req = inevow.IRequest(ctx)
|
|
|
|
return_to = get_arg(req, "return_to", None)
|
|
|
|
if return_to:
|
|
|
|
return T.div[T.a(href=return_to)["Return to parent directory"]]
|
|
|
|
return ""
|
|
|
|
|
|
|
|
class DeepCheckResults(rend.Page, ResultsBase):
|
2008-07-17 23:47:09 +00:00
|
|
|
docFactory = getxmlfile("deep-check-results.xhtml")
|
|
|
|
|
|
|
|
def __init__(self, results):
|
|
|
|
assert IDeepCheckResults(results)
|
|
|
|
self.r = results
|
|
|
|
|
|
|
|
def render_root_storage_index(self, ctx, data):
|
|
|
|
return self.r.get_root_storage_index_string()
|
|
|
|
|
|
|
|
def data_objects_checked(self, ctx, data):
|
2008-09-07 19:44:56 +00:00
|
|
|
return self.r.get_counters()["count-objects-checked"]
|
2008-07-17 23:47:09 +00:00
|
|
|
def data_objects_healthy(self, ctx, data):
|
2008-09-07 19:44:56 +00:00
|
|
|
return self.r.get_counters()["count-objects-healthy"]
|
|
|
|
def data_objects_unhealthy(self, ctx, data):
|
|
|
|
return self.r.get_counters()["count-objects-unhealthy"]
|
|
|
|
|
|
|
|
def data_count_corrupt_shares(self, ctx, data):
|
|
|
|
return self.r.get_counters()["count-corrupt-shares"]
|
|
|
|
|
|
|
|
def render_problems_p(self, ctx, data):
|
|
|
|
c = self.r.get_counters()
|
|
|
|
if c["count-objects-unhealthy"]:
|
|
|
|
return ctx.tag
|
|
|
|
return ""
|
2008-07-17 23:47:09 +00:00
|
|
|
|
|
|
|
def data_problems(self, ctx, data):
|
2008-09-07 19:44:56 +00:00
|
|
|
all_objects = self.r.get_all_results()
|
|
|
|
for path in sorted(all_objects.keys()):
|
|
|
|
cr = all_objects[path]
|
|
|
|
assert ICheckerResults.providedBy(cr)
|
|
|
|
if not cr.is_healthy():
|
|
|
|
yield path, cr
|
|
|
|
|
2008-08-12 04:03:26 +00:00
|
|
|
def render_problem(self, ctx, data):
|
2008-09-07 19:44:56 +00:00
|
|
|
path, cr = data
|
|
|
|
summary_text = ""
|
|
|
|
summary = cr.get_summary()
|
|
|
|
if summary:
|
|
|
|
summary_text = ": " + summary
|
|
|
|
summary_text += " [SI: %s]" % cr.get_storage_index_string()
|
|
|
|
return ctx.tag["/".join(self._html(path)), self._html(summary_text)]
|
|
|
|
|
|
|
|
|
|
|
|
def render_servers_with_corrupt_shares_p(self, ctx, data):
|
|
|
|
if self.r.get_counters()["count-corrupt-shares"]:
|
|
|
|
return ctx.tag
|
|
|
|
return ""
|
|
|
|
|
|
|
|
def data_servers_with_corrupt_shares(self, ctx, data):
|
|
|
|
servers = [serverid
|
|
|
|
for (serverid, storage_index, sharenum)
|
|
|
|
in self.r.get_corrupt_shares()]
|
|
|
|
servers.sort()
|
|
|
|
return servers
|
|
|
|
|
|
|
|
def render_server_problem(self, ctx, data):
|
|
|
|
serverid = data
|
|
|
|
data = [idlib.shortnodeid_b2a(serverid)]
|
|
|
|
c = IClient(ctx)
|
|
|
|
nickname = c.get_nickname_for_peerid(serverid)
|
|
|
|
if nickname:
|
|
|
|
data.append(" (%s)" % self._html(nickname))
|
|
|
|
return ctx.tag[data]
|
|
|
|
|
|
|
|
|
|
|
|
def render_corrupt_shares_p(self, ctx, data):
|
|
|
|
if self.r.get_counters()["count-corrupt-shares"]:
|
|
|
|
return ctx.tag
|
|
|
|
return ""
|
|
|
|
def data_corrupt_shares(self, ctx, data):
|
|
|
|
return self.r.get_corrupt_shares()
|
|
|
|
def render_share_problem(self, ctx, data):
|
|
|
|
serverid, storage_index, sharenum = data
|
|
|
|
nickname = IClient(ctx).get_nickname_for_peerid(serverid)
|
|
|
|
ctx.fillSlots("serverid", idlib.shortnodeid_b2a(serverid))
|
|
|
|
if nickname:
|
|
|
|
ctx.fillSlots("nickname", self._html(nickname))
|
|
|
|
ctx.fillSlots("si", base32.b2a(storage_index))
|
|
|
|
ctx.fillSlots("shnum", str(sharenum))
|
|
|
|
return ctx.tag
|
|
|
|
|
|
|
|
def render_return(self, ctx, data):
|
|
|
|
req = inevow.IRequest(ctx)
|
|
|
|
return_to = get_arg(req, "return_to", None)
|
|
|
|
if return_to:
|
|
|
|
return T.div[T.a(href=return_to)["Return to parent directory"]]
|
|
|
|
return ""
|
2008-08-12 04:03:26 +00:00
|
|
|
|
|
|
|
def data_all_objects(self, ctx, data):
|
|
|
|
r = self.r.get_all_results()
|
2008-09-07 19:44:56 +00:00
|
|
|
for path in sorted(r.keys()):
|
|
|
|
yield (path, r[path])
|
2008-08-12 04:03:26 +00:00
|
|
|
|
|
|
|
def render_object(self, ctx, data):
|
2008-09-07 19:44:56 +00:00
|
|
|
path, r = data
|
|
|
|
ctx.fillSlots("path", "/".join(self._html(path)))
|
2008-08-12 04:03:26 +00:00
|
|
|
ctx.fillSlots("healthy", str(r.is_healthy()))
|
2008-09-07 19:44:56 +00:00
|
|
|
ctx.fillSlots("summary", self._html(r.get_summary()))
|
2008-08-12 04:03:26 +00:00
|
|
|
return ctx.tag
|
2008-07-17 23:47:09 +00:00
|
|
|
|
2008-09-07 19:44:56 +00:00
|
|
|
def render_runtime(self, ctx, data):
|
|
|
|
req = inevow.IRequest(ctx)
|
|
|
|
runtime = time.time() - req.processing_started_timestamp
|
|
|
|
return ctx.tag["runtime: %s seconds" % runtime]
|
|
|
|
|
|
|
|
class DeepCheckAndRepairResults(rend.Page, ResultsBase):
|
|
|
|
docFactory = getxmlfile("deep-check-and-repair-results.xhtml")
|
|
|
|
|
|
|
|
def __init__(self, results):
|
|
|
|
assert IDeepCheckAndRepairResults(results)
|
|
|
|
self.r = results
|
|
|
|
|
|
|
|
def render_root_storage_index(self, ctx, data):
|
|
|
|
return self.r.get_root_storage_index_string()
|
|
|
|
|
|
|
|
def data_objects_checked(self, ctx, data):
|
|
|
|
return self.r.get_counters()["count-objects-checked"]
|
|
|
|
|
|
|
|
def data_objects_healthy(self, ctx, data):
|
|
|
|
return self.r.get_counters()["count-objects-healthy-pre-repair"]
|
|
|
|
def data_objects_unhealthy(self, ctx, data):
|
|
|
|
return self.r.get_counters()["count-objects-unhealthy-pre-repair"]
|
|
|
|
def data_corrupt_shares(self, ctx, data):
|
|
|
|
return self.r.get_counters()["count-corrupt-shares-pre-repair"]
|
|
|
|
|
|
|
|
def data_repairs_attempted(self, ctx, data):
|
|
|
|
return self.r.get_counters()["count-repairs-attempted"]
|
|
|
|
def data_repairs_successful(self, ctx, data):
|
|
|
|
return self.r.get_counters()["count-repairs-successful"]
|
|
|
|
def data_repairs_unsuccessful(self, ctx, data):
|
|
|
|
return self.r.get_counters()["count-repairs-unsuccessful"]
|
|
|
|
|
|
|
|
def data_objects_healthy_post(self, ctx, data):
|
|
|
|
return self.r.get_counters()["count-objects-healthy-post-repair"]
|
|
|
|
def data_objects_unhealthy_post(self, ctx, data):
|
|
|
|
return self.r.get_counters()["count-objects-unhealthy-post-repair"]
|
|
|
|
def data_corrupt_shares_post(self, ctx, data):
|
|
|
|
return self.r.get_counters()["count-corrupt-shares-post-repair"]
|
|
|
|
|
|
|
|
def render_pre_repair_problems_p(self, ctx, data):
|
|
|
|
c = self.r.get_counters()
|
|
|
|
if c["count-objects-unhealthy-pre-repair"]:
|
|
|
|
return ctx.tag
|
|
|
|
return ""
|
|
|
|
|
|
|
|
def data_pre_repair_problems(self, ctx, data):
|
|
|
|
all_objects = self.r.get_all_results()
|
|
|
|
for path in sorted(all_objects.keys()):
|
|
|
|
r = all_objects[path]
|
|
|
|
assert ICheckAndRepairResults.providedBy(r)
|
|
|
|
cr = r.get_pre_repair_results()
|
|
|
|
if not cr.is_healthy():
|
|
|
|
yield path, cr
|
|
|
|
|
|
|
|
def render_problem(self, ctx, data):
|
|
|
|
path, cr = data
|
|
|
|
return ["/".join(self._html(path)), ": ", self._html(cr.get_summary())]
|
|
|
|
|
|
|
|
def render_post_repair_problems_p(self, ctx, data):
|
|
|
|
c = self.r.get_counters()
|
|
|
|
if (c["count-objects-unhealthy-post-repair"]
|
|
|
|
or c["count-corrupt-shares-post-repair"]):
|
|
|
|
return ctx.tag
|
|
|
|
return ""
|
|
|
|
|
|
|
|
def data_post_repair_problems(self, ctx, data):
|
|
|
|
all_objects = self.r.get_all_results()
|
|
|
|
for path in sorted(all_objects.keys()):
|
|
|
|
r = all_objects[path]
|
|
|
|
assert ICheckAndRepairResults.providedBy(r)
|
|
|
|
cr = r.get_post_repair_results()
|
|
|
|
if not cr.is_healthy():
|
|
|
|
yield path, cr
|
|
|
|
|
|
|
|
def render_servers_with_corrupt_shares_p(self, ctx, data):
|
|
|
|
if self.r.get_counters()["count-corrupt-shares-pre-repair"]:
|
|
|
|
return ctx.tag
|
|
|
|
return ""
|
|
|
|
def data_servers_with_corrupt_shares(self, ctx, data):
|
|
|
|
return [] # TODO
|
|
|
|
def render_server_problem(self, ctx, data):
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
def render_remaining_corrupt_shares_p(self, ctx, data):
|
|
|
|
if self.r.get_counters()["count-corrupt-shares-post-repair"]:
|
|
|
|
return ctx.tag
|
|
|
|
return ""
|
|
|
|
def data_post_repair_corrupt_shares(self, ctx, data):
|
|
|
|
return [] # TODO
|
|
|
|
|
|
|
|
def render_share_problem(self, ctx, data):
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
2008-07-17 23:47:09 +00:00
|
|
|
def render_return(self, ctx, data):
|
|
|
|
req = inevow.IRequest(ctx)
|
|
|
|
return_to = get_arg(req, "return_to", None)
|
|
|
|
if return_to:
|
|
|
|
return T.div[T.a(href=return_to)["Return to parent directory"]]
|
|
|
|
return ""
|
2008-08-13 03:34:26 +00:00
|
|
|
|
2008-09-07 19:44:56 +00:00
|
|
|
def data_all_objects(self, ctx, data):
|
|
|
|
r = self.r.get_all_results()
|
|
|
|
for path in sorted(r.keys()):
|
|
|
|
yield (path, r[path])
|
|
|
|
|
|
|
|
def render_object(self, ctx, data):
|
|
|
|
path, r = data
|
|
|
|
ctx.fillSlots("path", "/".join(self._html(path)))
|
|
|
|
ctx.fillSlots("healthy_pre_repair",
|
|
|
|
str(r.get_pre_repair_results().is_healthy()))
|
|
|
|
ctx.fillSlots("healthy_post_repair",
|
|
|
|
str(r.get_post_repair_results().is_healthy()))
|
|
|
|
ctx.fillSlots("summary",
|
|
|
|
self._html(r.get_pre_repair_results().get_summary()))
|
|
|
|
return ctx.tag
|
|
|
|
|
2008-08-13 03:34:26 +00:00
|
|
|
def render_runtime(self, ctx, data):
|
|
|
|
req = inevow.IRequest(ctx)
|
|
|
|
runtime = time.time() - req.processing_started_timestamp
|
|
|
|
return ctx.tag["runtime: %s seconds" % runtime]
|