1# Copyright 2013 The Chromium Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""Implementation of CloudBucket using Google Cloud Storage as the backend."""
6import os
7import sys
8
9# boto requires depot_tools/third_party be in the path. Use
10# src/tools/find_depot_tools.py to add this directory.
11sys.path.append(os.path.join(os.path.dirname(__file__), os.pardir, os.pardir,
12                             os.pardir, os.pardir, 'tools'))
13import find_depot_tools
14DEPOT_TOOLS_PATH = find_depot_tools.add_depot_tools_to_path()
15sys.path.append(os.path.join(os.path.abspath(DEPOT_TOOLS_PATH), 'third_party'))
16import boto
17
18from ispy.common import cloud_bucket
19
20
21class BotoCloudBucket(cloud_bucket.BaseCloudBucket):
22  """Interfaces with GS using the boto library."""
23
24  def __init__(self, key, secret, bucket_name):
25    """Initializes the bucket with a key, secret, and bucket_name.
26
27    Args:
28      key: the API key to access GS.
29      secret: the API secret to access GS.
30      bucket_name: the name of the bucket to connect to.
31    """
32    uri = boto.storage_uri('', 'gs')
33    conn = uri.connect(key, secret)
34    self.bucket = conn.get_bucket(bucket_name)
35
36  def _GetKey(self, path):
37    key = boto.gs.key.Key(self.bucket)
38    key.key = path
39    return key
40
41  # override
42  def UploadFile(self, path, contents, content_type):
43    key = self._GetKey(path)
44    key.set_metadata('Content-Type', content_type)
45    key.set_contents_from_string(contents)
46    # Open permissions for the appengine account to read/write.
47    key.add_email_grant('FULL_CONTROL',
48        'ispy.google.com@appspot.gserviceaccount.com')
49
50  # override
51  def DownloadFile(self, path):
52    key = self._GetKey(path)
53    if key.exists():
54      return key.get_contents_as_string()
55    else:
56      raise cloud_bucket.FileNotFoundError
57
58  # override
59  def UpdateFile(self, path, contents):
60    key = self._GetKey(path)
61    if key.exists():
62      key.set_contents_from_string(contents)
63    else:
64      raise cloud_bucket.FileNotFoundError
65
66  # override
67  def RemoveFile(self, path):
68    key = self._GetKey(path)
69    key.delete()
70
71  # override
72  def FileExists(self, path):
73    key = self._GetKey(path)
74    return key.exists()
75
76  # override
77  def GetImageURL(self, path):
78    key = self._GetKey(path)
79    if key.exists():
80      # Corrects a bug in boto that incorrectly generates a url
81      #  to a resource in Google Cloud Storage.
82      return key.generate_url(3600).replace('AWSAccessKeyId', 'GoogleAccessId')
83    else:
84      raise cloud_bucket.FileNotFoundError(path)
85
86  # override
87  def GetAllPaths(self, prefix):
88    return (key.key for key in self.bucket.get_all_keys(prefix=prefix))
89