mirror of
https://github.com/tahoe-lafs/tahoe-lafs.git
synced 2025-04-08 19:34:18 +00:00
Merge PR430: add JSON welcome page
closes ticket:2476
This commit is contained in:
commit
d018a07bf0
@ -1850,6 +1850,40 @@ This is the "Welcome Page", and contains a few distinct sections::
|
||||
Grid status: introducer information, helper information, connected storage
|
||||
servers.
|
||||
|
||||
``GET /?t=json`` (the json welcome page)
|
||||
|
||||
This is the "json Welcome Page", and contains connectivity status
|
||||
of the introducer(s) and storage server(s), here's an example::
|
||||
|
||||
{
|
||||
"introducers": {
|
||||
"statuses": []
|
||||
},
|
||||
"servers": [{
|
||||
"nodeid": "other_nodeid",
|
||||
"available_space": 123456,
|
||||
"nickname": "George \u263b",
|
||||
"version": "1.0",
|
||||
"connection_status": "summary",
|
||||
"last_received_data": 1487811257
|
||||
}]
|
||||
}
|
||||
|
||||
|
||||
The above json ``introducers`` section includes a list of
|
||||
introducer connectivity status messages.
|
||||
|
||||
The above json ``servers`` section is an array with map elements. Each map
|
||||
has the following properties:
|
||||
|
||||
1. ``nodeid`` - an identifier derived from the node's public key
|
||||
2. ``available_space`` - the available space in bytes expressed as an integer
|
||||
3. ``nickname`` - the storage server nickname
|
||||
4. ``version`` - the storage server Tahoe-LAFS version
|
||||
5. ``connection_status`` - connectivity status
|
||||
6. ``last_received_data`` - the time when data was last received,
|
||||
expressed in seconds since epoch
|
||||
|
||||
``GET /status/``
|
||||
|
||||
This page lists all active uploads and downloads, and contains a short list
|
||||
|
@ -184,10 +184,15 @@ class FakeDisplayableServer(StubServer):
|
||||
self.last_loss_time = last_loss_time
|
||||
self.last_rx_time = last_rx_time
|
||||
self.last_connect_time = last_connect_time
|
||||
|
||||
def on_status_changed(self, cb): # TODO: try to remove me
|
||||
cb(self)
|
||||
def is_connected(self): # TODO: remove me
|
||||
return self.connected
|
||||
def get_version(self):
|
||||
return {
|
||||
"application-version": "1.0"
|
||||
}
|
||||
def get_permutation_seed(self):
|
||||
return ""
|
||||
def get_announcement(self):
|
||||
@ -257,7 +262,7 @@ class FakeClient(Client):
|
||||
last_connect_time = 10, last_loss_time = 20, last_rx_time = 30))
|
||||
self.storage_broker.test_add_server("disconnected_nodeid",
|
||||
FakeDisplayableServer(
|
||||
serverid="other_nodeid", nickname=u"disconnected_nickname \u263B", connected = False,
|
||||
serverid="disconnected_nodeid", nickname=u"disconnected_nickname \u263B", connected = False,
|
||||
last_connect_time = None, last_loss_time = 25, last_rx_time = 35))
|
||||
self.introducer_client = None
|
||||
self.history = FakeHistory()
|
||||
@ -734,6 +739,40 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
|
||||
def test_create(self):
|
||||
pass
|
||||
|
||||
maxDiff = None
|
||||
def test_welcome_json(self):
|
||||
"""
|
||||
There is a JSON version of the welcome page which can be selected with the
|
||||
``t`` query argument.
|
||||
"""
|
||||
d = self.GET("/?t=json")
|
||||
def _check(res):
|
||||
decoded = json.loads(res)
|
||||
expected = {
|
||||
u'introducers': {
|
||||
u'statuses': [],
|
||||
},
|
||||
u'servers': sorted([
|
||||
{u"nodeid": u'other_nodeid',
|
||||
u'available_space': 123456,
|
||||
u'connection_status': u'summary',
|
||||
u'last_received_data': 30,
|
||||
u'nickname': u'other_nickname \u263b',
|
||||
u'version': u'1.0',
|
||||
},
|
||||
{u"nodeid": u'disconnected_nodeid',
|
||||
u'available_space': 123456,
|
||||
u'connection_status': u'summary',
|
||||
u'last_received_data': 35,
|
||||
u'nickname': u'disconnected_nickname \u263b',
|
||||
u'version': u'1.0',
|
||||
},
|
||||
]),
|
||||
}
|
||||
self.assertEqual(expected, decoded)
|
||||
d.addCallback(_check)
|
||||
return d
|
||||
|
||||
def test_welcome(self):
|
||||
d = self.GET("/")
|
||||
def _check(res):
|
||||
|
@ -1,4 +1,4 @@
|
||||
import time, os
|
||||
import time, os, json
|
||||
|
||||
from twisted.web import http
|
||||
from nevow import rend, url, tags as T
|
||||
@ -12,8 +12,19 @@ from allmydata.util import log
|
||||
from allmydata.interfaces import IFileNode
|
||||
from allmydata.web import filenode, directory, unlinked, status, operations
|
||||
from allmydata.web import storage, magic_folder
|
||||
from allmydata.web.common import abbreviate_size, getxmlfile, WebError, \
|
||||
get_arg, RenderMixin, get_format, get_mutable_type, render_time_delta, render_time, render_time_attr
|
||||
from allmydata.web.common import (
|
||||
abbreviate_size,
|
||||
getxmlfile,
|
||||
WebError,
|
||||
get_arg,
|
||||
MultiFormatPage,
|
||||
RenderMixin,
|
||||
get_format,
|
||||
get_mutable_type,
|
||||
render_time_delta,
|
||||
render_time,
|
||||
render_time_attr,
|
||||
)
|
||||
|
||||
|
||||
class URIHandler(RenderMixin, rend.Page):
|
||||
@ -126,7 +137,7 @@ class IncidentReporter(RenderMixin, rend.Page):
|
||||
|
||||
SPACE = u"\u00A0"*2
|
||||
|
||||
class Root(rend.Page):
|
||||
class Root(MultiFormatPage):
|
||||
|
||||
addSlash = True
|
||||
docFactory = getxmlfile("welcome.xhtml")
|
||||
@ -182,9 +193,50 @@ class Root(rend.Page):
|
||||
def render_my_nodeid(self, ctx, data):
|
||||
tubid_s = "TubID: "+self.client.get_long_tubid()
|
||||
return T.td(title=tubid_s)[self.client.get_long_nodeid()]
|
||||
|
||||
def data_my_nickname(self, ctx, data):
|
||||
return self.client.nickname
|
||||
|
||||
|
||||
def render_JSON(self, req):
|
||||
req.setHeader("content-type", "application/json; charset=utf-8")
|
||||
intro_summaries = [s.summary for s in self.client.introducer_connection_statuses()]
|
||||
sb = self.client.get_storage_broker()
|
||||
servers = self._describe_known_servers(sb)
|
||||
result = {
|
||||
"introducers": {
|
||||
"statuses": intro_summaries,
|
||||
},
|
||||
"servers": servers
|
||||
}
|
||||
return json.dumps(result, indent=1) + "\n"
|
||||
|
||||
|
||||
def _describe_known_servers(self, broker):
|
||||
return sorted(list(
|
||||
self._describe_server(server)
|
||||
for server
|
||||
in broker.get_known_servers()
|
||||
))
|
||||
|
||||
|
||||
def _describe_server(self, server):
|
||||
status = server.get_connection_status()
|
||||
description = {
|
||||
u"nodeid": server.get_serverid(),
|
||||
u"connection_status": status.summary,
|
||||
u"available_space": server.get_available_space(),
|
||||
u"nickname": server.get_nickname(),
|
||||
u"version": None,
|
||||
u"last_received_data": status.last_received_time,
|
||||
}
|
||||
version = server.get_version()
|
||||
if version is not None:
|
||||
description[u"version"] = version["application-version"]
|
||||
|
||||
return description
|
||||
|
||||
|
||||
def render_magic_folder(self, ctx, data):
|
||||
if self.client._magic_folder is None:
|
||||
return T.p()
|
||||
|
Loading…
x
Reference in New Issue
Block a user