]> git.rkrishnan.org Git - tahoe-lafs/tahoe-lafs.git/commitdiff
Use a private/drop_upload_dircap file instead of the [drop_upload]upload.dircap optio...
authordavid-sarah <david-sarah@jacaranda.org>
Sun, 20 Nov 2011 23:24:26 +0000 (23:24 +0000)
committerdavid-sarah <david-sarah@jacaranda.org>
Sun, 20 Nov 2011 23:24:26 +0000 (23:24 +0000)
docs/frontends/drop-upload.rst
src/allmydata/client.py
src/allmydata/node.py
src/allmydata/scripts/create_node.py
src/allmydata/test/test_client.py

index 02746882d6cd9985fe11be5d0d307f3d1ccc6a56..1b6b0937d1b783ac1a42c8bade6c2d259c744a46 100644 (file)
@@ -20,8 +20,8 @@ Tahoe-LAFS Summit in June 2011, and is not currently in as mature a state as
 the other frontends (web, CLI, FTP and SFTP). This means that you probably
 should not keep important data in the upload directory, and should not rely
 on all changes to files in the local directory to result in successful uploads.
-There might be incompatible changes to how the feature is configured in
-future versions. There is even the possibility that it may be abandoned, for
+There might be (and have been) incompatible changes to how the feature is
+configured. There is even the possibility that it may be abandoned, for
 example if unsolveable reliability issues are found.
 
 We are very interested in feedback on how well this feature works for you, and
@@ -42,15 +42,8 @@ gateway's ``tahoe.cfg`` file.
 
 ``enabled = (boolean, optional)``
 
-    If this is ``True``, drop-upload will be enabled (provided that the
-    ``upload.dircap`` and ``local.directory`` fields are also set). The
-    default value is ``False``.
-
-``upload.dircap = (directory writecap)``
-
-    This is a writecap pointing to an existing mutable directory to be used
-    as the target of uploads. It will start with ``URI:DIR2:``, and cannot
-    include an alias or path.
+    If this is ``True``, drop-upload will be enabled. The default value is
+    ``False``.
 
 ``local.directory = (UTF-8 path)``
 
@@ -59,6 +52,11 @@ gateway's ``tahoe.cfg`` file.
     in UTF-8 regardless of the system's filesystem encoding. Relative paths
     will be interpreted starting from the node's base directory.
 
+In addition, the file  ``private/drop_upload_dircap`` must contain a
+writecap pointing to an existing mutable directory to be used as the target
+of uploads. It will start with ``URI:DIR2:``, and cannot include an alias
+or path.
+
 After setting the above fields and starting or restarting the gateway,
 you can confirm that the feature is working by copying a file into the
 local directory. Then, use the WUI or CLI to check that it has appeared
index 813ee3959a2c61ec1789e4f1537aef2325e2ce2c..b78fd7b9641ff3eb87f97ad6eb96b82e2169e902 100644 (file)
@@ -26,6 +26,7 @@ from allmydata.interfaces import IStatsProducer, RIStubClient, \
                                  SDMF_VERSION, MDMF_VERSION
 from allmydata.nodemaker import NodeMaker
 from allmydata.blacklist import Blacklist
+from allmydata.node import OldConfigOptionError
 
 
 KiB=1024
@@ -439,19 +440,20 @@ class Client(node.Node, pollmixin.PollMixin):
 
     def init_drop_uploader(self):
         if self.get_config("drop_upload", "enabled", False, boolean=True):
-            upload_dircap = self.get_config("drop_upload", "upload.dircap", None)
-            local_dir_utf8 = self.get_config("drop_upload", "local.directory", None)
-
-            if upload_dircap and local_dir_utf8:
-                try:
-                    from allmydata.frontends import drop_upload
-                    s = drop_upload.DropUploader(self, upload_dircap, local_dir_utf8)
-                    s.setServiceParent(self)
-                    s.startService()
-                except Exception, e:
-                    self.log("couldn't start drop-uploader: %r", args=(e,))
-            else:
-                self.log("couldn't start drop-uploader: upload.dircap or local.directory not specified")
+            if self.get_config("drop_upload", "upload.dircap", None):
+                raise OldConfigOptionError("The [drop_upload]upload.dircap option is no longer supported; please "
+                                           "put the cap in a 'private/drop_upload_dircap' file, and delete this option.")
+
+            upload_dircap = self.get_or_create_private_config("drop_upload_dircap")
+            local_dir_utf8 = self.get_config("drop_upload", "local.directory")
+
+            try:
+                from allmydata.frontends import drop_upload
+                s = drop_upload.DropUploader(self, upload_dircap, local_dir_utf8)
+                s.setServiceParent(self)
+                s.startService()
+            except Exception, e:
+                self.log("couldn't start drop-uploader: %r", args=(e,))
 
     def _check_hotline(self, hotline_file):
         if os.path.exists(hotline_file):
index eefce3d6a9d98ae50ec35b715bff52eef3bd987f..0b8436502790e7f45ef59990dd792823e3ba2b6a 100644 (file)
@@ -52,6 +52,9 @@ class OldConfigError(Exception):
                 "See docs/historical/configuration.rst."
                 % "\n".join([quote_output(fname) for fname in self.args[0]]))
 
+class OldConfigOptionError(Exception):
+    pass
+
 
 class Node(service.MultiService):
     # this implements common functionality of both Client nodes and Introducer
@@ -201,21 +204,27 @@ class Node(service.MultiService):
         privname = os.path.join(self.basedir, "private", name)
         open(privname, "w").write(value.strip())
 
-    def get_or_create_private_config(self, name, default):
+    def get_or_create_private_config(self, name, default=_None):
         """Try to get the (string) contents of a private config file (which
         is a config file that resides within the subdirectory named
         'private'), and return it. Any leading or trailing whitespace will be
         stripped from the data.
 
-        If the file does not exist, try to create it using default, and
-        then return the value that was written. If 'default' is a string,
-        use it as a default value. If not, treat it as a 0-argument callable
-        which is expected to return a string.
+        If the file does not exist, and default is not given, report an error.
+        If the file does not exist and a default is specified, try to create
+        it using that default, and then return the value that was written.
+        If 'default' is a string, use it as a default value. If not, treat it
+        as a zero-argument callable that is expected to return a string.
         """
         privname = os.path.join(self.basedir, "private", name)
         try:
             value = fileutil.read(privname)
         except EnvironmentError:
+            if os.path.exists(privname):
+                raise
+            if default is _None:
+                raise MissingConfigEntry("The required configuration file %s is missing."
+                                         % (quote_output(privname),))
             if isinstance(default, basestring):
                 value = default
             else:
index 294f6dd82f0d3c3c0d01236cf83df13e2f3862a3..7e9dcf7912a50279d673c9702ebd3db4517e6790 100644 (file)
@@ -155,8 +155,8 @@ def create_node(config, out=sys.stdout, err=sys.stderr):
     c.write("[drop_upload]\n")
     c.write("# Shall this node automatically upload files created or modified in a local directory?\n")
     c.write("enabled = false\n")
-    c.write("# This must be a mutable directory writecap.\n")
-    c.write("upload.dircap =\n")
+    c.write("# To specify the target of uploads, a mutable directory writecap URI must be placed\n"
+            "# in 'private/drop_upload_dircap'.\n")
     c.write("local.directory = ~/drop_upload\n")
     c.write("\n")
 
index 26af511804d5bf1ee1c1b54670edf66381af766c..14c9c791a9341e03c0bb5938ff30ca370a3afc87 100644 (file)
@@ -3,7 +3,7 @@ from twisted.trial import unittest
 from twisted.application import service
 
 import allmydata
-from allmydata.node import OldConfigError
+from allmydata.node import OldConfigError, OldConfigOptionError, MissingConfigEntry
 from allmydata import client
 from allmydata.storage_client import StorageFarmBroker
 from allmydata.util import base32, fileutil
@@ -191,13 +191,24 @@ class Basic(testutil.ReallyEqualMixin, unittest.TestCase):
                   "[storage]\n" +
                   "enabled = false\n" +
                   "[drop_upload]\n" +
-                  "enabled = true\n" +
-                  "upload.dircap = " + upload_dircap + "\n" +
-                  "local.directory = " + local_dir_utf8 + "\n")
+                  "enabled = true\n")
 
         basedir1 = "test_client.Basic.test_create_drop_uploader1"
         os.mkdir(basedir1)
+        fileutil.write(os.path.join(basedir1, "tahoe.cfg"),
+                       config + "local.directory = " + local_dir_utf8 + "\n")
+        self.failUnlessRaises(MissingConfigEntry, client.Client, basedir1)
+
         fileutil.write(os.path.join(basedir1, "tahoe.cfg"), config)
+        fileutil.write(os.path.join(basedir1, "private", "drop_upload_dircap"), "URI:DIR2:blah")
+        self.failUnlessRaises(MissingConfigEntry, client.Client, basedir1)
+
+        fileutil.write(os.path.join(basedir1, "tahoe.cfg"),
+                       config + "upload.dircap = " + upload_dircap + "\n")
+        self.failUnlessRaises(OldConfigOptionError, client.Client, basedir1)
+
+        fileutil.write(os.path.join(basedir1, "tahoe.cfg"),
+                       config + "local.directory = " + local_dir_utf8 + "\n")
         c1 = client.Client(basedir1)
         uploader = c1.getServiceNamed('drop-upload')
         self.failUnless(isinstance(uploader, MockDropUploader), uploader)
@@ -213,21 +224,15 @@ class Basic(testutil.ReallyEqualMixin, unittest.TestCase):
 
         basedir2 = "test_client.Basic.test_create_drop_uploader2"
         os.mkdir(basedir2)
+        os.mkdir(os.path.join(basedir2, "private"))
         fileutil.write(os.path.join(basedir2, "tahoe.cfg"),
                        BASECONFIG +
                        "[drop_upload]\n" +
-                       "enabled = true\n")
+                       "enabled = true\n" +
+                       "local.directory = " + local_dir_utf8 + "\n")
+        fileutil.write(os.path.join(basedir2, "private", "drop_upload_dircap"), "URI:DIR2:blah")
         c2 = client.Client(basedir2)
         self.failUnlessRaises(KeyError, c2.getServiceNamed, 'drop-upload')
-        self.failIf([True for arg in mock_log_msg.call_args_list if "Boom" in repr(arg)],
-                    mock_log_msg.call_args_list)
-        self.failUnless([True for arg in mock_log_msg.call_args_list if "upload.dircap or local.directory not specified" in repr(arg)],
-                        mock_log_msg.call_args_list)
-
-        basedir3 = "test_client.Basic.test_create_drop_uploader3"
-        os.mkdir(basedir3)
-        fileutil.write(os.path.join(basedir3, "tahoe.cfg"), config)
-        client.Client(basedir3)
         self.failUnless([True for arg in mock_log_msg.call_args_list if "Boom" in repr(arg)],
                         mock_log_msg.call_args_list)