From: Brian Warner Date: Fri, 20 Feb 2009 23:03:53 +0000 (-0700) Subject: web/storage: make sure we can handle platforms without os.statvfs too X-Git-Tag: allmydata-tahoe-1.4.0~168 X-Git-Url: https://git.rkrishnan.org/COPYING.GPL?a=commitdiff_plain;h=2e45619844cb7c3604b25d2dd41329f1ecf385ed;p=tahoe-lafs%2Ftahoe-lafs.git web/storage: make sure we can handle platforms without os.statvfs too --- diff --git a/src/allmydata/storage/server.py b/src/allmydata/storage/server.py index 7971113d..4840cc53 100644 --- a/src/allmydata/storage/server.py +++ b/src/allmydata/storage/server.py @@ -131,6 +131,9 @@ class StorageServer(service.MultiService, Referenceable): def _clean_incomplete(self): fileutil.rm_dir(self.incomingdir) + def do_statvfs(self): + return os.statvfs(self.storedir) + def get_stats(self): # remember: RIStatsProvider requires that our return dict # contains numeric values. @@ -143,7 +146,7 @@ class StorageServer(service.MultiService, Referenceable): if self.readonly_storage: writeable = False try: - s = os.statvfs(self.storedir) + s = self.do_statvfs() disk_total = s.f_bsize * s.f_blocks disk_used = s.f_bsize * (s.f_blocks - s.f_bfree) # spacetime predictors should look at the slope of disk_used. diff --git a/src/allmydata/test/test_storage.py b/src/allmydata/test/test_storage.py index d5723247..d8788098 100644 --- a/src/allmydata/test/test_storage.py +++ b/src/allmydata/test/test_storage.py @@ -1290,6 +1290,9 @@ class Stats(unittest.TestCase): self.failUnless(abs(output["get"]["99_0_percentile"] - 5) < 1) self.failUnless(abs(output["get"]["99_9_percentile"] - 5) < 1) +class NoStatvfsServer(StorageServer): + def do_statvfs(self): + raise AttributeError class WebStatus(unittest.TestCase): @@ -1315,6 +1318,19 @@ class WebStatus(unittest.TestCase): self.failUnless("Accepting new shares: Yes" in s, s) self.failUnless("Reserved space: - 0B" in s, s) + def test_status_no_statvfs(self): + # windows has no os.statvfs . Make sure the code handles that even on + # unix. + basedir = "storage/WebStatus/status_no_statvfs" + fileutil.make_dirs(basedir) + ss = NoStatvfsServer(basedir, "\x00" * 20) + w = StorageStatus(ss) + html = w.renderSynchronously() + self.failUnless("

Storage Server Status

" in html, html) + s = self.remove_tags(html) + self.failUnless("Accepting new shares: Yes" in s, s) + self.failUnless("Total disk space: ?" in s, s) + def test_readonly(self): basedir = "storage/WebStatus/readonly" fileutil.make_dirs(basedir) diff --git a/src/allmydata/web/storage.py b/src/allmydata/web/storage.py index 013cedb9..a8698a47 100644 --- a/src/allmydata/web/storage.py +++ b/src/allmydata/web/storage.py @@ -37,11 +37,27 @@ class StorageStatus(rend.Page): # object in self.original that gets passed to render_* methods. I # still don't understand Nevow. - # all xhtml tags that are children of a tag with n:render="stats" - # will be processed with this dictionary, so something like: + # Nevow has nevow.accessors.DictionaryContainer: Any data= directive + # that appears in a context in which the current data is a dictionary + # will be looked up as keys in that dictionary. So if data_stats() + # returns a dictionary, then we can use something like this: + # # - # will use get_stats()["storage_server.disk_total"] - return dict([ (remove_prefix(k, "storage_server."), v) - for k,v in self.storage.get_stats().items() ]) + + # to use get_stats()["storage_server.disk_total"] . However, + # DictionaryContainer does a raw d[] instead of d.get(), so any + # missing keys will cause an error, even if the renderer can tolerate + # None values. To overcome this, we either need a dict-like object + # that always returns None for unknown keys, or we must pre-populate + # our dict with those missing keys (or find some way to override + # Nevow's handling of dictionaries). + + d = dict([ (remove_prefix(k, "storage_server."), v) + for k,v in self.storage.get_stats().items() ]) + d.setdefault("disk_total", None) + d.setdefault("disk_used", None) + d.setdefault("reserved_space", None) + d.setdefault("disk_avail", None) + return d