]> git.rkrishnan.org Git - tahoe-lafs/tahoe-lafs.git/commitdiff
web/storage: make sure we can handle platforms without os.statvfs too
authorBrian Warner <warner@lothar.com>
Fri, 20 Feb 2009 23:03:53 +0000 (16:03 -0700)
committerBrian Warner <warner@lothar.com>
Fri, 20 Feb 2009 23:03:53 +0000 (16:03 -0700)
src/allmydata/storage/server.py
src/allmydata/test/test_storage.py
src/allmydata/web/storage.py

index 7971113d6e81ddc98e0c19ef9dd0d1e4aa9b583c..4840cc53f3af199d1115f1964dfa7ceb34c26a94 100644 (file)
@@ -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.
index d5723247df7e0c9501a65e62e4f436669b11935b..d87880988519350513c9a6afa6e1eddb429840c2 100644 (file)
@@ -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("<h1>Storage Server Status</h1>" 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)
index 013cedb9fd62b62d936f353ba99dfcfea9760159..a8698a47ddb0c57875ebd540cf0379fc66942a9d 100644 (file)
@@ -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:
+        #
         #  <ul n:data="stats">
-        #   <li>disk_total: <span n:data="disk_total" /></li>
+        #   <li>disk_total: <span n:render="abbrev" n:data="disk_total" /></li>
         #  </ul>
-        # 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