Update status page child route handler and table renderers

Drop nevow-isms and use twisted.web's way of doing things.
This commit is contained in:
Sajith Sasidharan 2020-05-22 22:10:40 -04:00
parent 3357f4c5ce
commit a6e32135e8

View File

@ -25,6 +25,7 @@ from allmydata.web.common import (
render_time, render_time,
MultiFormatPage, MultiFormatPage,
MultiFormatResource, MultiFormatResource,
SlotsSequenceElement,
) )
from allmydata.interfaces import ( from allmydata.interfaces import (
@ -1127,8 +1128,6 @@ def marshal_json(s):
class Status(MultiFormatResource): class Status(MultiFormatResource):
addSlash = True
def __init__(self, history): def __init__(self, history):
super(Status, self).__init__() super(Status, self).__init__()
self.history = history self.history = history
@ -1153,45 +1152,24 @@ class Status(MultiFormatResource):
return json.dumps(data, indent=1) + "\n" return json.dumps(data, indent=1) + "\n"
def _get_all_statuses(self): def getChild(self, path, request):
h = self.history # The "if (path is empty) return self" line should handle
return itertools.chain(h.list_all_upload_statuses(), # trailing slash in request path.
h.list_all_download_statuses(), #
h.list_all_mapupdate_statuses(), # Twisted Web's documentation says this: "If the URL ends in a
h.list_all_publish_statuses(), # slash, for example ``http://example.com/foo/bar/`` , the
h.list_all_retrieve_statuses(), # final URL segment will be an empty string. Resources can
h.list_all_helper_statuses(), # thus know if they were requested with or without a final
) # slash."
if not path:
return self
def data_active_operations(self, ctx, data):
return self._get_active_operations()
def _get_active_operations(self):
active = [s
for s in self._get_all_statuses()
if s.get_active()]
active.sort(lambda a, b: cmp(a.get_started(), b.get_started()))
active.reverse()
return active
def data_recent_operations(self, ctx, data):
return self._get_recent_operations()
def _get_recent_operations(self):
recent = [s
for s in self._get_all_statuses()
if not s.get_active()]
recent.sort(lambda a, b: cmp(a.get_started(), b.get_started()))
recent.reverse()
return recent
def childFactory(self, ctx, name):
h = self.history h = self.history
try: try:
stype, count_s = name.split("-") stype, count_s = path.split("-")
except ValueError: except ValueError:
raise RuntimeError( raise RuntimeError(
"no - in '{}'".format(name) "no - in '{}'".format(path)
) )
count = int(count_s) count = int(count_s)
if stype == "up": if stype == "up":
@ -1218,6 +1196,32 @@ class Status(MultiFormatResource):
if s.get_counter() == count: if s.get_counter() == count:
return RetrieveStatusPage(s) return RetrieveStatusPage(s)
def _get_all_statuses(self):
h = self.history
return itertools.chain(h.list_all_upload_statuses(),
h.list_all_download_statuses(),
h.list_all_mapupdate_statuses(),
h.list_all_publish_statuses(),
h.list_all_retrieve_statuses(),
h.list_all_helper_statuses(),
)
def _get_active_operations(self):
active = [s
for s in self._get_all_statuses()
if s.get_active()]
active.sort(lambda a, b: cmp(a.get_started(), b.get_started()))
active.reverse()
return active
def _get_recent_operations(self):
recent = [s
for s in self._get_all_statuses()
if not s.get_active()]
recent.sort(lambda a, b: cmp(a.get_started(), b.get_started()))
recent.reverse()
return recent
class StatusElement(Element): class StatusElement(Element):
@ -1229,56 +1233,70 @@ class StatusElement(Element):
self._recent = recent self._recent = recent
@renderer @renderer
def row(self, req, tag): def active_operations(self, req, tag):
s = data active = [self.get_op_state(op) for op in self._active]
return SlotsSequenceElement(tag, active)
started_s = render_time(s.get_started()) @renderer
ctx.fillSlots("started", started_s) def recent_operations(self, req, tag):
active = [self.get_op_state(op) for op in self._recent]
return SlotsSequenceElement(tag, active)
si_s = base32.b2a_or_none(s.get_storage_index()) @staticmethod
def get_op_state(op):
result = dict()
started_s = render_time(op.get_started())
result.update({"started": started_s})
si_s = base32.b2a_or_none(op.get_storage_index())
if si_s is None: if si_s is None:
si_s = "(None)" si_s = "(None)"
ctx.fillSlots("si", si_s)
ctx.fillSlots("helper", {True: "Yes",
False: "No"}[s.using_helper()])
size = s.get_size() result.update({"si": si_s})
result.update({"helper":
{True: "Yes", False: "No"}[op.using_helper()]})
size = op.get_size()
if size is None: if size is None:
size = "(unknown)" size = "(unknown)"
elif isinstance(size, (int, long, float)): elif isinstance(size, (int, long, float)):
size = abbreviate_size(size) size = abbreviate_size(size)
ctx.fillSlots("total_size", size)
progress = data.get_progress() result.update({"total_size": size})
if IUploadStatus.providedBy(data):
link = "up-%d" % data.get_counter() progress = op.get_progress()
ctx.fillSlots("type", "upload") if IUploadStatus.providedBy(op):
link = "up-%d" % op.get_counter()
result.update({"type": "upload"})
# TODO: make an ascii-art bar # TODO: make an ascii-art bar
(chk, ciphertext, encandpush) = progress (chk, ciphertext, encandpush) = progress
progress_s = ("hash: %.1f%%, ciphertext: %.1f%%, encode: %.1f%%" % progress_s = ("hash: %.1f%%, ciphertext: %.1f%%, encode: %.1f%%" %
( (100.0 * chk), ((100.0 * chk),
(100.0 * ciphertext), (100.0 * ciphertext),
(100.0 * encandpush) )) (100.0 * encandpush)))
ctx.fillSlots("progress", progress_s) result.update({"progress": progress_s})
elif IDownloadStatus.providedBy(data): elif IDownloadStatus.providedBy(op):
link = "down-%d" % data.get_counter() link = "down-%d" % op.get_counter()
ctx.fillSlots("type", "download") result.update({"type": "download"})
ctx.fillSlots("progress", "%.1f%%" % (100.0 * progress)) result.update({"progress": "%.1f%%" % (100.0 * progress)})
elif IPublishStatus.providedBy(data): elif IPublishStatus.providedBy(op):
link = "publish-%d" % data.get_counter() link = "publish-%d" % op.get_counter()
ctx.fillSlots("type", "publish") result.update({"type": "publish"})
ctx.fillSlots("progress", "%.1f%%" % (100.0 * progress)) result.update({"progress": "%.1f%%" % (100.0 * progress)})
elif IRetrieveStatus.providedBy(data): elif IRetrieveStatus.providedBy(op):
ctx.fillSlots("type", "retrieve") result.update({"type": "retrieve"})
link = "retrieve-%d" % data.get_counter() link = "retrieve-%d" % op.get_counter()
ctx.fillSlots("progress", "%.1f%%" % (100.0 * progress)) result.update({"progress": "%.1f%%" % (100.0 * progress)})
else: else:
assert IServermapUpdaterStatus.providedBy(data) assert IServermapUpdaterStatus.providedBy(op)
ctx.fillSlots("type", "mapupdate %s" % data.get_mode()) result.update({"type": "mapupdate %s" % op.get_mode()})
link = "mapupdate-%d" % data.get_counter() link = "mapupdate-%d" % op.get_counter()
ctx.fillSlots("progress", "%.1f%%" % (100.0 * progress)) result.update({"progress": "%.1f%%" % (100.0 * progress)})
ctx.fillSlots("status", T.a(href=link)[s.get_status()])
return ctx.tag result.update({"status": tags.a(op.get_status(), href=link)})
return result
# Render "/helper_status" page. # Render "/helper_status" page.