Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(67)

Side by Side Diff: gslib/cloud_api_delegator.py

Issue 698893003: Update checked in version of gsutil to version 4.6 (Closed) Base URL: http://dart.googlecode.com/svn/third_party/gsutil/
Patch Set: Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « gslib/cloud_api.py ('k') | gslib/cloud_api_helper.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 # -*- coding: utf-8 -*-
2 # Copyright 2013 Google Inc. All Rights Reserved.
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 """Gsutil API delegator for interacting with cloud storage providers."""
16
17 from __future__ import absolute_import
18
19 import boto
20 from boto import config
21 from gslib.cloud_api import ArgumentException
22 from gslib.cloud_api import CloudApi
23 from gslib.cs_api_map import ApiMapConstants
24 from gslib.cs_api_map import ApiSelector
25
26
27 class CloudApiDelegator(CloudApi):
28 """Class that handles delegating requests to gsutil Cloud API implementations.
29
30 This class is responsible for determining at runtime which gsutil Cloud API
31 implementation should service the request based on the Cloud storage provider,
32 command-level API support, and configuration file override.
33
34 During initialization it takes as an argument a gsutil_api_map which maps
35 providers to their default and supported gsutil Cloud API implementations
36 (see comments in cs_api_map for details).
37
38 Instantiation of multiple delegators per-thread is required for multiprocess
39 and/or multithreaded operations. Calling methods on the same delegator in
40 multiple threads is unsafe.
41 """
42
43 def __init__(self, bucket_storage_uri_class, gsutil_api_map, logger,
44 provider=None, debug=0):
45 """Performs necessary setup for delegating cloud storage requests.
46
47 This function has different arguments than the gsutil Cloud API __init__
48 function because of the delegation responsibilties of this class.
49
50 Args:
51 bucket_storage_uri_class: boto storage_uri class, used by APIs that
52 provide boto translation or mocking.
53 gsutil_api_map: Map of providers and API selector tuples to api classes
54 which can be used to communicate with those providers.
55 logger: logging.logger for outputting log messages.
56 provider: Default provider prefix describing cloud storage provider to
57 connect to.
58 debug: Debug level for the API implementation (0..3).
59 """
60 super(CloudApiDelegator, self).__init__(bucket_storage_uri_class, logger,
61 provider=provider, debug=debug)
62 self.api_map = gsutil_api_map
63 self.prefer_api = boto.config.get('GSUtil', 'prefer_api', '').upper()
64 self.loaded_apis = {}
65
66 if not self.api_map[ApiMapConstants.API_MAP]:
67 raise ArgumentException('No apiclass supplied for gsutil Cloud API map.')
68
69 def _GetApi(self, provider):
70 """Returns a valid CloudApi for use by the caller.
71
72 This function lazy-loads connection and credentials using the API map
73 and credential store provided during class initialization.
74
75 Args:
76 provider: Provider to load API for. If None, class-wide default is used.
77
78 Raises:
79 ArgumentException if there is no matching API available in the API map.
80
81 Returns:
82 Valid API instance that can be used to communicate with the Cloud
83 Storage provider.
84 """
85 provider = provider or self.provider
86 if not provider:
87 raise ArgumentException('No provider selected for _GetApi')
88
89 provider = str(provider)
90 if provider not in self.loaded_apis:
91 self.loaded_apis[provider] = {}
92
93 api_selector = self.GetApiSelector(provider)
94 if api_selector not in self.loaded_apis[provider]:
95 # Need to load the API.
96 self._LoadApi(provider, api_selector)
97
98 return self.loaded_apis[provider][api_selector]
99
100 def _LoadApi(self, provider, api_selector):
101 """Loads a CloudApi into the loaded_apis map for this class.
102
103 Args:
104 provider: Provider to load the API for.
105 api_selector: cs_api_map.ApiSelector defining the API type.
106 """
107 if provider not in self.api_map[ApiMapConstants.API_MAP]:
108 raise ArgumentException(
109 'gsutil Cloud API map contains no entry for provider %s.' % provider)
110 if api_selector not in self.api_map[ApiMapConstants.API_MAP][provider]:
111 raise ArgumentException(
112 'gsutil Cloud API map does not support API %s for provider %s.' %
113 (api_selector, provider))
114 self.loaded_apis[provider][api_selector] = (
115 self.api_map[ApiMapConstants.API_MAP][provider][api_selector](
116 self.bucket_storage_uri_class,
117 self.logger,
118 provider=provider,
119 debug=self.debug))
120
121 def GetApiSelector(self, provider=None):
122 """Returns a cs_api_map.ApiSelector based on input and configuration.
123
124 Args:
125 provider: Provider to return the ApiSelector for. If None, class-wide
126 default is used.
127
128 Returns:
129 cs_api_map.ApiSelector that will be used for calls to the delegator
130 for this provider.
131 """
132 selected_provider = provider or self.provider
133 if not selected_provider:
134 raise ArgumentException('No provider selected for CloudApi')
135
136 if (selected_provider not in self.api_map[ApiMapConstants.DEFAULT_MAP] or
137 self.api_map[ApiMapConstants.DEFAULT_MAP][selected_provider] not in
138 self.api_map[ApiMapConstants.API_MAP][selected_provider]):
139 raise ArgumentException('No default api available for provider %s' %
140 selected_provider)
141
142 if selected_provider not in self.api_map[ApiMapConstants.SUPPORT_MAP]:
143 raise ArgumentException('No supported apis available for provider %s' %
144 selected_provider)
145
146 api = self.api_map[ApiMapConstants.DEFAULT_MAP][selected_provider]
147
148 # If we have only HMAC credentials for Google Cloud Storage, we must use
149 # the XML API as the JSON API does not support HMAC.
150 #
151 # Technically if we have only HMAC credentials, we should still be able to
152 # access public read resources via the JSON API, but the XML API can do
153 # that just as well. It is better to use it than inspect the credentials on
154 # every HTTP call.
155 if (provider == 'gs' and
156 not config.has_option('Credentials', 'gs_oauth2_refresh_token') and
157 not (config.has_option('Credentials', 'gs_service_client_id')
158 and config.has_option('Credentials', 'gs_service_key_file')) and
159 (config.has_option('Credentials', 'gs_access_key_id')
160 and config.has_option('Credentials', 'gs_secret_access_key'))):
161 api = ApiSelector.XML
162 # Try to force the user's preference to a supported API.
163 elif self.prefer_api in (self.api_map[ApiMapConstants.SUPPORT_MAP]
164 [selected_provider]):
165 api = self.prefer_api
166 return api
167
168 # For function docstrings, see CloudApi class.
169 def GetBucket(self, bucket_name, provider=None, fields=None):
170 return self._GetApi(provider).GetBucket(bucket_name, fields=fields)
171
172 def ListBuckets(self, project_id=None, provider=None, fields=None):
173 return self._GetApi(provider).ListBuckets(project_id=project_id,
174 fields=fields)
175
176 def PatchBucket(self, bucket_name, metadata, preconditions=None,
177 provider=None, fields=None):
178 return self._GetApi(provider).PatchBucket(
179 bucket_name, metadata, preconditions=preconditions, fields=fields)
180
181 def CreateBucket(self, bucket_name, project_id=None, metadata=None,
182 provider=None, fields=None):
183 return self._GetApi(provider).CreateBucket(
184 bucket_name, project_id=project_id, metadata=metadata, fields=fields)
185
186 def DeleteBucket(self, bucket_name, preconditions=None, provider=None):
187 return self._GetApi(provider).DeleteBucket(bucket_name,
188 preconditions=preconditions)
189
190 def ListObjects(self, bucket_name, prefix=None, delimiter=None,
191 all_versions=None, provider=None, fields=None):
192 return self._GetApi(provider).ListObjects(
193 bucket_name, prefix=prefix, delimiter=delimiter,
194 all_versions=all_versions, fields=fields)
195
196 def GetObjectMetadata(self, bucket_name, object_name, generation=None,
197 provider=None, fields=None):
198 return self._GetApi(provider).GetObjectMetadata(
199 bucket_name, object_name, generation=generation, fields=fields)
200
201 def PatchObjectMetadata(self, bucket_name, object_name, metadata,
202 generation=None, preconditions=None, provider=None,
203 fields=None):
204 return self._GetApi(provider).PatchObjectMetadata(
205 bucket_name, object_name, metadata, generation=generation,
206 preconditions=preconditions, fields=fields)
207
208 def GetObjectMedia(
209 self, bucket_name, object_name, download_stream, provider=None,
210 generation=None, object_size=None,
211 download_strategy=CloudApi.DownloadStrategy.ONE_SHOT,
212 start_byte=0, end_byte=None, progress_callback=None,
213 serialization_data=None, digesters=None):
214 return self._GetApi(provider).GetObjectMedia(
215 bucket_name, object_name, download_stream,
216 download_strategy=download_strategy, start_byte=start_byte,
217 end_byte=end_byte, generation=generation, object_size=object_size,
218 progress_callback=progress_callback,
219 serialization_data=serialization_data, digesters=digesters)
220
221 def UploadObject(self, upload_stream, object_metadata, size=None,
222 canned_acl=None, preconditions=None, progress_callback=None,
223 provider=None, fields=None):
224 return self._GetApi(provider).UploadObject(
225 upload_stream, object_metadata, size=size, canned_acl=canned_acl,
226 preconditions=preconditions, progress_callback=progress_callback,
227 fields=fields)
228
229 def UploadObjectStreaming(self, upload_stream, object_metadata,
230 canned_acl=None, preconditions=None,
231 progress_callback=None, provider=None, fields=None):
232 return self._GetApi(provider).UploadObjectStreaming(
233 upload_stream, object_metadata, canned_acl=canned_acl,
234 preconditions=preconditions, progress_callback=progress_callback,
235 fields=fields)
236
237 def UploadObjectResumable(
238 self, upload_stream, object_metadata, canned_acl=None, preconditions=None,
239 provider=None, fields=None, size=None, serialization_data=None,
240 tracker_callback=None, progress_callback=None):
241 return self._GetApi(provider).UploadObjectResumable(
242 upload_stream, object_metadata, canned_acl=canned_acl,
243 preconditions=preconditions, size=size, fields=fields,
244 serialization_data=serialization_data,
245 tracker_callback=tracker_callback, progress_callback=progress_callback)
246
247 def CopyObject(self, src_bucket_name, src_obj_name, dst_obj_metadata,
248 src_generation=None, canned_acl=None, preconditions=None,
249 provider=None, fields=None):
250 return self._GetApi(provider).CopyObject(
251 src_bucket_name, src_obj_name, dst_obj_metadata,
252 src_generation=src_generation, canned_acl=canned_acl,
253 preconditions=preconditions, fields=fields)
254
255 def ComposeObject(self, src_objs_metadata, dst_obj_metadata,
256 preconditions=None, provider=None, fields=None):
257 return self._GetApi(provider).ComposeObject(
258 src_objs_metadata, dst_obj_metadata, preconditions=preconditions,
259 fields=fields)
260
261 def DeleteObject(self, bucket_name, object_name, preconditions=None,
262 generation=None, provider=None):
263 return self._GetApi(provider).DeleteObject(
264 bucket_name, object_name, preconditions=preconditions,
265 generation=generation)
266
267 def WatchBucket(self, bucket_name, address, channel_id, token=None,
268 provider=None, fields=None):
269 return self._GetApi(provider).WatchBucket(
270 bucket_name, address, channel_id, token=token, fields=fields)
271
272 def StopChannel(self, channel_id, resource_id, provider=None):
273 return self._GetApi(provider).StopChannel(channel_id, resource_id)
274
275 def XmlPassThroughGetAcl(self, storage_url, def_obj_acl=False, provider=None):
276 """XML compatibility function for getting ACLs.
277
278 Args:
279 storage_url: StorageUrl object.
280 def_obj_acl: If true, get the default object ACL on a bucket.
281 provider: Cloud storage provider to connect to. If not present,
282 class-wide default is used.
283
284 Raises:
285 ArgumentException for errors during input validation.
286 ServiceException for errors interacting with cloud storage providers.
287
288 Returns:
289 ACL XML for the resource specified by storage_url.
290 """
291 return self._GetApi(provider).XmlPassThroughGetAcl(storage_url,
292 def_obj_acl=def_obj_acl)
293
294 def XmlPassThroughSetAcl(self, acl_text, storage_url, canned=True,
295 def_obj_acl=False, provider=None):
296 """XML compatibility function for setting ACLs.
297
298 Args:
299 acl_text: XML ACL or canned ACL string.
300 storage_url: StorageUrl object.
301 canned: If true, acl_text is treated as a canned ACL string.
302 def_obj_acl: If true, set the default object ACL on a bucket.
303 provider: Cloud storage provider to connect to. If not present,
304 class-wide default is used.
305
306 Raises:
307 ArgumentException for errors during input validation.
308 ServiceException for errors interacting with cloud storage providers.
309
310 Returns:
311 None.
312 """
313 self._GetApi(provider).XmlPassThroughSetAcl(
314 acl_text, storage_url, canned=canned, def_obj_acl=def_obj_acl)
315
316 def XmlPassThroughGetCors(self, storage_url, provider=None):
317 """XML compatibility function for getting CORS configuration on a bucket.
318
319 Args:
320 storage_url: StorageUrl object.
321 provider: Cloud storage provider to connect to. If not present,
322 class-wide default is used.
323
324 Raises:
325 ArgumentException for errors during input validation.
326 ServiceException for errors interacting with cloud storage providers.
327
328 Returns:
329 CORS configuration XML for the bucket specified by storage_url.
330 """
331 return self._GetApi(provider).XmlPassThroughGetCors(storage_url)
332
333 def XmlPassThroughSetCors(self, cors_text, storage_url, provider=None):
334 """XML compatibility function for setting CORS configuration on a bucket.
335
336 Args:
337 cors_text: Raw CORS XML string.
338 storage_url: StorageUrl object.
339 provider: Cloud storage provider to connect to. If not present,
340 class-wide default is used.
341
342 Raises:
343 ArgumentException for errors during input validation.
344 ServiceException for errors interacting with cloud storage providers.
345
346 Returns:
347 None.
348 """
349 self._GetApi(provider).XmlPassThroughSetCors(cors_text, storage_url)
350
351 def XmlPassThroughGetLifecycle(self, storage_url, provider=None):
352 """XML compatibility function for getting lifecycle config on a bucket.
353
354 Args:
355 storage_url: StorageUrl object.
356 provider: Cloud storage provider to connect to. If not present,
357 class-wide default is used.
358
359 Raises:
360 ArgumentException for errors during input validation.
361 ServiceException for errors interacting with cloud storage providers.
362
363 Returns:
364 Lifecycle configuration XML for the bucket specified by storage_url.
365 """
366 return self._GetApi(provider).XmlPassThroughGetLifecycle(storage_url)
367
368 def XmlPassThroughSetLifecycle(self, lifecycle_text, storage_url,
369 provider=None):
370 """XML compatibility function for setting CORS configuration on a bucket.
371
372 Args:
373 lifecycle_text: Raw lifecycle configuration XML string.
374 storage_url: StorageUrl object.
375 provider: Cloud storage provider to connect to. If not present,
376 class-wide default is used.
377
378 Raises:
379 ArgumentException for errors during input validation.
380 ServiceException for errors interacting with cloud storage providers.
381
382 Returns:
383 None.
384 """
385 self._GetApi(provider).XmlPassThroughSetLifecycle(lifecycle_text,
386 storage_url)
387
388 def XmlPassThroughGetLogging(self, storage_url, provider=None):
389 """XML compatibility function for getting logging configuration on a bucket.
390
391 Args:
392 storage_url: StorageUrl object.
393 provider: Cloud storage provider to connect to. If not present,
394 class-wide default is used.
395
396 Raises:
397 ArgumentException for errors during input validation.
398 ServiceException for errors interacting with cloud storage providers.
399
400 Returns:
401 Logging configuration XML for the bucket specified by storage_url.
402 """
403 return self._GetApi(provider).XmlPassThroughGetLogging(storage_url)
404
405 def XmlPassThroughGetWebsite(self, storage_url, provider=None):
406 """XML compatibility function for getting website configuration on a bucket.
407
408 Args:
409 storage_url: StorageUrl object.
410 provider: Cloud storage provider to connect to. If not present,
411 class-wide default is used.
412
413 Raises:
414 ArgumentException for errors during input validation.
415 ServiceException for errors interacting with cloud storage providers.
416
417 Returns:
418 Website configuration XML for the bucket specified by storage_url.
419 """
420 return self._GetApi(provider).XmlPassThroughGetWebsite(storage_url)
421
OLDNEW
« no previous file with comments | « gslib/cloud_api.py ('k') | gslib/cloud_api_helper.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698