From: Itamar Turner-Trauring <itamar@futurefoundries.com>
Date: Tue, 5 Mar 2013 16:38:40 +0000 (-0500)
Subject: Configuration support for Google Cloud Storage backend.
X-Git-Url: https://git.rkrishnan.org/%5B/frontends//%22news.html/%22?a=commitdiff_plain;h=169bd634e83ff97ba049e0f5c75562de9e91935d;p=tahoe-lafs%2Ftahoe-lafs.git

Configuration support for Google Cloud Storage backend.
---

diff --git a/src/allmydata/storage/backends/cloud/cloud_backend.py b/src/allmydata/storage/backends/cloud/cloud_backend.py
index 3d92525f..14dee749 100644
--- a/src/allmydata/storage/backends/cloud/cloud_backend.py
+++ b/src/allmydata/storage/backends/cloud/cloud_backend.py
@@ -20,7 +20,7 @@ from allmydata.storage.backends.cloud.cloud_common import get_share_key, delete_
 from allmydata.mutable.layout import MUTABLE_MAGIC
 
 
-CLOUD_INTERFACES = ("cloud.s3", "cloud.openstack")
+CLOUD_INTERFACES = ("cloud.s3", "cloud.openstack", "cloud.googlestorage")
 
 
 def get_cloud_share(container, storage_index, shnum, total_size):
diff --git a/src/allmydata/storage/backends/cloud/googlestorage/googlestorage_container.py b/src/allmydata/storage/backends/cloud/googlestorage/googlestorage_container.py
index 75264e23..af3a82a9 100644
--- a/src/allmydata/storage/backends/cloud/googlestorage/googlestorage_container.py
+++ b/src/allmydata/storage/backends/cloud/googlestorage/googlestorage_container.py
@@ -26,12 +26,6 @@ from allmydata.storage.backends.cloud.cloud_common import IContainer, \
      ContainerItem, ContainerListing, CommonContainerMixin
 
 
-def configure_googlestorage_container(*args):
-    """
-    Configure the Google Cloud Storage container.
-    """
-
-
 class AuthenticationClient(object):
     """
     Retrieve access tokens for the Google Storage API, using OAuth 2.0.
@@ -227,19 +221,16 @@ class GoogleStorageContainer(CommonContainerMixin):
         return d
 
 
-if __name__ == '__main__':
-    from twisted.internet import reactor
-    from twisted.web.client import getPage
-    import sys
-    auth = AuthenticationClient(sys.argv[1], file(sys.argv[2]).read())
-    def println(result):
-        print result
-        reactor.stop()
-    def gotAuth(value):
-        return getPage("https://storage.googleapis.com/",
-                       headers={"Authorization": value,
-                                "x-goog-api-version": "2",
-                                "x-goog-project-id": sys.argv[3]}).addCallback(println)
-    auth.get_authorization_header().addCallback(gotAuth)
-    reactor.run()
-
+def configure_googlestorage_container(storedir, config):
+    """
+    Configure the Google Cloud Storage container.
+    """
+    account_email = config.get_config("storage", "googlestorage.account_email")
+    private_key = config.get_private_config("googlestorage_private_key")
+    bucket_name = config.get_config("storage", "googlestorage.bucket_name")
+    # Only necessary if we do bucket creation/deletion, otherwise can be
+    # removed:
+    project_id = config.get_config("storage", "googlestorage.project_id")
+
+    authclient = AuthenticationClient(account_email, private_key)
+    return GoogleStorageContainer(authclient, project_id, bucket_name)
diff --git a/src/allmydata/test/test_client.py b/src/allmydata/test/test_client.py
index 0888a0b6..bb7a086a 100644
--- a/src/allmydata/test/test_client.py
+++ b/src/allmydata/test/test_client.py
@@ -430,6 +430,74 @@ class Basic(testutil.ReallyEqualMixin, unittest.TestCase):
                                     "openstack.container = test\n")
         self.failUnlessRaises(MissingConfigEntry, client.Client, basedir)
 
+    def test_googlestorage_config_required(self):
+        """
+        account_email, bucket_name and project_id are all required by
+        googlestorage configuration.
+        """
+        configs = ["googlestorage.account_email = u@example.com",
+                   "googlestorage.bucket_name = bucket",
+                   "googlestorage.project_id = 456"]
+        for i in range(len(configs)):
+            basedir = self.mktemp()
+            os.mkdir(basedir)
+            bad_config = configs[:]
+            del bad_config[i]
+            self._write_secret(basedir, "googlestorage_private_key")
+            fileutil.write(os.path.join(basedir, "tahoe.cfg"),
+                           BASECONFIG +
+                           "[storage]\n" +
+                           "enabled = true\n" +
+                           "backend = cloud.googlestorage\n" +
+                           "\n".join(bad_config) + "\n")
+            self.failUnlessRaises(MissingConfigEntry, client.Client, basedir)
+
+    def test_googlestorage_config_required_private_key(self):
+        """
+        googlestorage_private_key secret is required by googlestorage
+        configuration.
+        """
+        basedir = self.mktemp()
+        os.mkdir(basedir)
+        fileutil.write(os.path.join(basedir, "tahoe.cfg"),
+                       BASECONFIG +
+                       "[storage]\n" +
+                       "enabled = true\n" +
+                       "backend = cloud.googlestorage\n" +
+                       "googlestorage.account_email = u@example.com\n" +
+                       "googlestorage.bucket_name = bucket\n" +
+                       "googlestorage.project_id = 456\n")
+        self.failUnlessRaises(MissingConfigEntry, client.Client, basedir)
+
+    @mock.patch('allmydata.storage.backends.cloud.googlestorage.googlestorage_container.AuthenticationClient')
+    @mock.patch('allmydata.storage.backends.cloud.googlestorage.googlestorage_container.GoogleStorageContainer')
+    def test_googlestorage_config(self, mock_OpenStackContainer, mock_AuthenticationClient):
+        """
+        Given good configuration, we correctly configure a good GoogleStorageContainer.
+        """
+        basedir = self.mktemp()
+        os.mkdir(basedir)
+        self._write_secret(basedir, "googlestorage_private_key", "sekrit")
+        fileutil.write(os.path.join(basedir, "tahoe.cfg"),
+                       BASECONFIG +
+                       "[storage]\n" +
+                       "enabled = true\n" +
+                       "backend = cloud.googlestorage\n" +
+                       "googlestorage.account_email = u@example.com\n" +
+                       "googlestorage.bucket_name = bucket\n" +
+                       "googlestorage.project_id = 456\n")
+        c = client.Client(basedir)
+        server = c.getServiceNamed("storage")
+        self.failUnless(isinstance(server.backend, CloudBackend), server.backend)
+        # Protect against typos with isinstance(), because mock is dangerous.
+        self.assertFalse(isinstance(mock_AuthenticationClient.assert_called_once_with,
+                                    mock.Mock))
+        mock_AuthenticationClient.assert_called_once_with("u@example.com", "sekrit")
+        self.assertFalse(isinstance(mock_OpenStackContainer.assert_called_once_with,
+                                    mock.Mock))
+        mock_OpenStackContainer.assert_called_once_with(mock_AuthenticationClient.return_value,
+                                                        "456", "bucket")
+
     def test_expire_mutable_false_unsupported(self):
         basedir = "client.Basic.test_expire_mutable_false_unsupported"
         os.mkdir(basedir)