From: Brian Warner Date: Sat, 26 Jul 2008 00:41:10 +0000 (-0700) Subject: web: add /status/?t=json, with active upload/download ops. Addresses #493. X-Git-Url: https://git.rkrishnan.org/?a=commitdiff_plain;h=914783acdf271a4f59967b58767827b5775da68b;p=tahoe-lafs%2Ftahoe-lafs.git web: add /status/?t=json, with active upload/download ops. Addresses #493. --- diff --git a/docs/webapi.txt b/docs/webapi.txt index ea5a4eca..44d16087 100644 --- a/docs/webapi.txt +++ b/docs/webapi.txt @@ -754,6 +754,45 @@ GET /status/ that describes file sizes, servers that were involved, and the time consumed in each phase of the operation. + A GET of /status/?t=json will contain a machine-readable subset of the same + data. It returns a JSON-encoded dictionary. The only key defined at this + time is "active", with a value that is a list of operation dictionaries, one + for each active operation. Once an operation is completed, it will no longer + appear in data["active"] . + + Each op-dict contains a "type" key, one of "upload", "download", + "mapupdate", "publish", or "retrieve" (the first two are for immutable + files, while the latter three are for mutable files and directories). + + The "upload" op-dict will contain the following keys: + + type (string): "upload" + storage-index-string (string): a base32-encoded storage index + total-size (int): total size of the file + status (string): current status of the operation + progress-hash (float): 1.0 when the file has been hashed + progress-ciphertext (float): 1.0 when the file has been encrypted. + progress-encode-push (float): 1.0 when the file has been encoded and + pushed to the storage servers. For helper + uploads, the ciphertext value climbs to 1.0 + first, then encoding starts. For unassisted + uploads, ciphertext and encode-push progress + will climb at the same pace. + + The "download" op-dict will contain the following keys: + + type (string): "download" + storage-index-string (string): a base32-encoded storage index + total-size (int): total size of the file + status (string): current status of the operation + progress (float): 1.0 when the file has been fully downloaded + + Front-ends which want to report progress information are advised to simply + average together all the progress-* indicators. A slightly more accurate + value can be found by ignoring the progress-hash value (since the current + implementation hashes synchronously, so clients will probably never see + progress-hash!=1.0). + GET /provisioning/ This page provides a basic tool to predict the likely storage and bandwidth diff --git a/src/allmydata/test/test_web.py b/src/allmydata/test/test_web.py index da1b5ec8..b794f8d4 100644 --- a/src/allmydata/test/test_web.py +++ b/src/allmydata/test/test_web.py @@ -438,6 +438,15 @@ class Web(WebMixin, unittest.TestCase): self.failUnless('"publish-%d"' % pub_num in res, res) self.failUnless('"retrieve-%d"' % ret_num in res, res) d.addCallback(_check) + d.addCallback(lambda res: self.GET("/status/?t=json")) + def _check_json(res): + data = simplejson.loads(res) + self.failUnless(isinstance(data, dict)) + active = data["active"] + # TODO: test more. We need a way to fake an active operation + # here. + d.addCallback(_check_json) + d.addCallback(lambda res: self.GET("/status/down-%d" % dl_num)) def _check_dl(res): self.failUnless("File Download Status" in res, res) diff --git a/src/allmydata/web/status.py b/src/allmydata/web/status.py index c2d429ef..2c9bafaa 100644 --- a/src/allmydata/web/status.py +++ b/src/allmydata/web/status.py @@ -772,6 +772,41 @@ class Status(rend.Page): docFactory = getxmlfile("status.xhtml") addSlash = True + def renderHTTP(self, ctx): + t = get_arg(inevow.IRequest(ctx), "t") + if t == "json": + return self.json(ctx) + return rend.Page.renderHTTP(self, ctx) + + def json(self, ctx): + inevow.IRequest(ctx).setHeader("content-type", "text/plain") + client = IClient(ctx) + data = {} + data["active"] = active = [] + for s in self.data_active_operations(ctx, None): + si_s = base32.b2a_or_none(s.get_storage_index()) + size = s.get_size() + status = s.get_status() + if IUploadStatus.providedBy(s): + h,c,e = s.get_progress() + active.append({"type": "upload", + "storage-index-string": si_s, + "total-size": size, + "status": status, + "progress-hash": h, + "progress-ciphertext": c, + "progress-encode-push": e, + }) + elif IDownloadStatus.providedBy(s): + active.append({"type": "download", + "storage-index-string": si_s, + "total-size": size, + "status": status, + "progress": s.get_progress(), + }) + + return simplejson.dumps(data, indent=1) + def _get_all_statuses(self, client): return itertools.chain(client.list_all_upload_statuses(), client.list_all_download_statuses(),