1c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch# Copyright 2013 The Chromium Authors. All rights reserved.
2c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch# Use of this source code is governed by a BSD-style license that can be
3c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch# found in the LICENSE file.
4c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
5c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch"""Implementation of CloudBucket using Google Cloud Storage as the backend."""
6c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochimport os
7c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochimport sys
8c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
9c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochimport cloudstorage
10c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
11c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochfrom common import cloud_bucket
12c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
13c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
14c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochclass GoogleCloudStorageBucket(cloud_bucket.BaseCloudBucket):
15c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  """Subclass of cloud_bucket.CloudBucket with actual GS commands."""
16c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
17c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  def __init__(self, bucket):
18c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    """Initializes the bucket.
19c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
20c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    Args:
21c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      bucket: the name of the bucket to connect to.
22c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    """
23c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    self.bucket = '/' + bucket
24c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
25c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  def _full_path(self, path):
26c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return self.bucket + '/' + path.lstrip('/')
27c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
28c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  # override
29c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  def UploadFile(self, path, contents, content_type):
30c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    gs_file = cloudstorage.open(
31c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        self._full_path(path), 'w', content_type=content_type)
32c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    gs_file.write(contents)
33c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    gs_file.close()
34c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
35c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  # override
36c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  def DownloadFile(self, path):
37c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    try:
38c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      gs_file = cloudstorage.open(self._full_path(path), 'r')
39c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      r = gs_file.read()
40c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      gs_file.close()
41c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    except Exception as e:
42c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      raise Exception('%s: %s' % (self._full_path(path), str(e)))
43c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return r
44c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
45c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  # override
46c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  def UpdateFile(self, path, contents):
47c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    if not self.FileExists(path):
48c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      raise cloud_bucket.FileNotFoundError
49c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    gs_file = cloudstorage.open(self._full_path(path), 'w')
50c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    gs_file.write(contents)
51c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    gs_file.close()
52c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
53c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  # override
54c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  def RemoveFile(self, path):
55c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    cloudstorage.delete(self._full_path(path))
56c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
57c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  # override
58c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  def FileExists(self, path):
59c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    try:
60c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      cloudstorage.stat(self._full_path(path))
61c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    except cloudstorage.NotFoundError:
62c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      return False
63c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return True
64c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
65c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  # override
66c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  def GetImageURL(self, path):
67c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return '/image?file_path=%s' % path
68c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
69c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  # override
70116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  def GetAllPaths(self, prefix, max_keys=None, marker=None, delimiter=None):
71c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return (f.filename[len(self.bucket) + 1:] for f in
72116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch            cloudstorage.listbucket(self.bucket, prefix=prefix,
73116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                max_keys=max_keys, marker=marker, delimiter=delimiter))
74