OLD | NEW |
1 # Copyright (c) 2006-2011 Mitch Garnaat http://garnaat.org/ | 1 # Copyright (c) 2006-2011 Mitch Garnaat http://garnaat.org/ |
2 # Copyright (c) 2010-2011, Eucalyptus Systems, Inc. | 2 # Copyright (c) 2010-2011, Eucalyptus Systems, Inc. |
| 3 # Copyright (c) 2011, Nexenta Systems Inc. |
3 # All rights reserved. | 4 # All rights reserved. |
4 # | 5 # |
5 # Permission is hereby granted, free of charge, to any person obtaining a | 6 # Permission is hereby granted, free of charge, to any person obtaining a |
6 # copy of this software and associated documentation files (the | 7 # copy of this software and associated documentation files (the |
7 # "Software"), to deal in the Software without restriction, including | 8 # "Software"), to deal in the Software without restriction, including |
8 # without limitation the rights to use, copy, modify, merge, publish, dis- | 9 # without limitation the rights to use, copy, modify, merge, publish, dis- |
9 # tribute, sublicense, and/or sell copies of the Software, and to permit | 10 # tribute, sublicense, and/or sell copies of the Software, and to permit |
10 # persons to whom the Software is furnished to do so, subject to the fol- | 11 # persons to whom the Software is furnished to do so, subject to the fol- |
11 # lowing conditions: | 12 # lowing conditions: |
12 # | 13 # |
13 # The above copyright notice and this permission notice shall be included | 14 # The above copyright notice and this permission notice shall be included |
14 # in all copies or substantial portions of the Software. | 15 # in all copies or substantial portions of the Software. |
15 # | 16 # |
16 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | 17 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
17 # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- | 18 # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- |
18 # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT | 19 # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT |
19 # SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | 20 # SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
20 # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | 21 # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
21 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | 22 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
22 # IN THE SOFTWARE. | 23 # IN THE SOFTWARE. |
23 # | 24 # |
24 import boto | |
25 from boto.pyami.config import Config, BotoConfigLocations | 25 from boto.pyami.config import Config, BotoConfigLocations |
26 from boto.storage_uri import BucketStorageUri, FileStorageUri | 26 from boto.storage_uri import BucketStorageUri, FileStorageUri |
27 import boto.plugin | 27 import boto.plugin |
28 import os, re, sys | 28 import os, re, sys |
29 import logging | 29 import logging |
30 import logging.config | 30 import logging.config |
31 from boto.exception import InvalidUriError | 31 from boto.exception import InvalidUriError |
32 | 32 |
33 __version__ = '2.0b4' | 33 __version__ = '2.1.1' |
34 Version = __version__ # for backware compatibility | 34 Version = __version__ # for backware compatibility |
35 | 35 |
36 UserAgent = 'Boto/%s (%s)' % (__version__, sys.platform) | 36 UserAgent = 'Boto/%s (%s)' % (__version__, sys.platform) |
37 config = Config() | 37 config = Config() |
38 | 38 |
39 def init_logging(): | 39 def init_logging(): |
40 for file in BotoConfigLocations: | 40 for file in BotoConfigLocations: |
41 try: | 41 try: |
42 logging.config.fileConfig(os.path.expanduser(file)) | 42 logging.config.fileConfig(os.path.expanduser(file)) |
43 except: | 43 except: |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
102 | 102 |
103 :rtype: :class:`boto.s3.connection.S3Connection` | 103 :rtype: :class:`boto.s3.connection.S3Connection` |
104 :return: A connection to Amazon's S3 | 104 :return: A connection to Amazon's S3 |
105 """ | 105 """ |
106 from boto.s3.connection import S3Connection | 106 from boto.s3.connection import S3Connection |
107 return S3Connection(aws_access_key_id, aws_secret_access_key, **kwargs) | 107 return S3Connection(aws_access_key_id, aws_secret_access_key, **kwargs) |
108 | 108 |
109 def connect_gs(gs_access_key_id=None, gs_secret_access_key=None, **kwargs): | 109 def connect_gs(gs_access_key_id=None, gs_secret_access_key=None, **kwargs): |
110 """ | 110 """ |
111 @type gs_access_key_id: string | 111 @type gs_access_key_id: string |
112 @param gs_access_key_id: Your Google Storage Access Key ID | 112 @param gs_access_key_id: Your Google Cloud Storage Access Key ID |
113 | 113 |
114 @type gs_secret_access_key: string | 114 @type gs_secret_access_key: string |
115 @param gs_secret_access_key: Your Google Storage Secret Access Key | 115 @param gs_secret_access_key: Your Google Cloud Storage Secret Access Key |
116 | 116 |
117 @rtype: L{GSConnection<boto.gs.connection.GSConnection>} | 117 @rtype: L{GSConnection<boto.gs.connection.GSConnection>} |
118 @return: A connection to Google's Storage service | 118 @return: A connection to Google's Storage service |
119 """ | 119 """ |
120 from boto.gs.connection import GSConnection | 120 from boto.gs.connection import GSConnection |
121 return GSConnection(gs_access_key_id, gs_secret_access_key, **kwargs) | 121 return GSConnection(gs_access_key_id, gs_secret_access_key, **kwargs) |
122 | 122 |
123 def connect_ec2(aws_access_key_id=None, aws_secret_access_key=None, **kwargs): | 123 def connect_ec2(aws_access_key_id=None, aws_secret_access_key=None, **kwargs): |
124 """ | 124 """ |
125 :type aws_access_key_id: string | 125 :type aws_access_key_id: string |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
257 :rtype: :class:`boto.rds.RDSConnection` | 257 :rtype: :class:`boto.rds.RDSConnection` |
258 :return: A connection to RDS | 258 :return: A connection to RDS |
259 """ | 259 """ |
260 from boto.rds import RDSConnection | 260 from boto.rds import RDSConnection |
261 return RDSConnection(aws_access_key_id, aws_secret_access_key, **kwargs) | 261 return RDSConnection(aws_access_key_id, aws_secret_access_key, **kwargs) |
262 | 262 |
263 def connect_emr(aws_access_key_id=None, aws_secret_access_key=None, **kwargs): | 263 def connect_emr(aws_access_key_id=None, aws_secret_access_key=None, **kwargs): |
264 """ | 264 """ |
265 :type aws_access_key_id: string | 265 :type aws_access_key_id: string |
266 :param aws_access_key_id: Your AWS Access Key ID | 266 :param aws_access_key_id: Your AWS Access Key ID |
267 | 267 |
268 :type aws_secret_access_key: string | 268 :type aws_secret_access_key: string |
269 :param aws_secret_access_key: Your AWS Secret Access Key | 269 :param aws_secret_access_key: Your AWS Secret Access Key |
270 | 270 |
271 :rtype: :class:`boto.emr.EmrConnection` | 271 :rtype: :class:`boto.emr.EmrConnection` |
272 :return: A connection to Elastic mapreduce | 272 :return: A connection to Elastic mapreduce |
273 """ | 273 """ |
274 from boto.emr import EmrConnection | 274 from boto.emr import EmrConnection |
275 return EmrConnection(aws_access_key_id, aws_secret_access_key, **kwargs) | 275 return EmrConnection(aws_access_key_id, aws_secret_access_key, **kwargs) |
276 | 276 |
277 def connect_sns(aws_access_key_id=None, aws_secret_access_key=None, **kwargs): | 277 def connect_sns(aws_access_key_id=None, aws_secret_access_key=None, **kwargs): |
278 """ | 278 """ |
279 :type aws_access_key_id: string | 279 :type aws_access_key_id: string |
280 :param aws_access_key_id: Your AWS Access Key ID | 280 :param aws_access_key_id: Your AWS Access Key ID |
(...skipping 29 matching lines...) Expand all Loading... |
310 | 310 |
311 :type aws_secret_access_key: string | 311 :type aws_secret_access_key: string |
312 :param aws_secret_access_key: Your AWS Secret Access Key | 312 :param aws_secret_access_key: Your AWS Secret Access Key |
313 | 313 |
314 :rtype: :class:`boto.dns.Route53Connection` | 314 :rtype: :class:`boto.dns.Route53Connection` |
315 :return: A connection to Amazon's Route53 DNS Service | 315 :return: A connection to Amazon's Route53 DNS Service |
316 """ | 316 """ |
317 from boto.route53 import Route53Connection | 317 from boto.route53 import Route53Connection |
318 return Route53Connection(aws_access_key_id, aws_secret_access_key, **kwargs) | 318 return Route53Connection(aws_access_key_id, aws_secret_access_key, **kwargs) |
319 | 319 |
320 def connect_euca(host, aws_access_key_id=None, aws_secret_access_key=None, | 320 def connect_euca(host=None, aws_access_key_id=None, aws_secret_access_key=None, |
321 port=8773, path='/services/Eucalyptus', is_secure=False, | 321 port=8773, path='/services/Eucalyptus', is_secure=False, |
322 **kwargs): | 322 **kwargs): |
323 """ | 323 """ |
324 Connect to a Eucalyptus service. | 324 Connect to a Eucalyptus service. |
325 | 325 |
326 :type host: string | 326 :type host: string |
327 :param host: the host name or ip address of the Eucalyptus server | 327 :param host: the host name or ip address of the Eucalyptus server |
328 | 328 |
329 :type aws_access_key_id: string | 329 :type aws_access_key_id: string |
330 :param aws_access_key_id: Your AWS Access Key ID | 330 :param aws_access_key_id: Your AWS Access Key ID |
331 | 331 |
332 :type aws_secret_access_key: string | 332 :type aws_secret_access_key: string |
333 :param aws_secret_access_key: Your AWS Secret Access Key | 333 :param aws_secret_access_key: Your AWS Secret Access Key |
334 | 334 |
335 :rtype: :class:`boto.ec2.connection.EC2Connection` | 335 :rtype: :class:`boto.ec2.connection.EC2Connection` |
336 :return: A connection to Eucalyptus server | 336 :return: A connection to Eucalyptus server |
337 """ | 337 """ |
338 from boto.ec2 import EC2Connection | 338 from boto.ec2 import EC2Connection |
339 from boto.ec2.regioninfo import RegionInfo | 339 from boto.ec2.regioninfo import RegionInfo |
340 | 340 |
| 341 # Check for values in boto config, if not supplied as args |
| 342 if not aws_access_key_id: |
| 343 aws_access_key_id = config.get('Credentials', |
| 344 'euca_access_key_id', |
| 345 None) |
| 346 if not aws_secret_access_key: |
| 347 aws_secret_access_key = config.get('Credentials', |
| 348 'euca_secret_access_key', |
| 349 None) |
| 350 if not host: |
| 351 host = config.get('Boto', 'eucalyptus_host', None) |
| 352 |
341 reg = RegionInfo(name='eucalyptus', endpoint=host) | 353 reg = RegionInfo(name='eucalyptus', endpoint=host) |
342 return EC2Connection(aws_access_key_id, aws_secret_access_key, | 354 return EC2Connection(aws_access_key_id, aws_secret_access_key, |
343 region=reg, port=port, path=path, | 355 region=reg, port=port, path=path, |
344 is_secure=is_secure, **kwargs) | 356 is_secure=is_secure, **kwargs) |
345 | 357 |
346 def connect_walrus(host, aws_access_key_id=None, aws_secret_access_key=None, | 358 def connect_walrus(host=None, aws_access_key_id=None, aws_secret_access_key=None
, |
347 port=8773, path='/services/Walrus', is_secure=False, | 359 port=8773, path='/services/Walrus', is_secure=False, |
348 **kwargs): | 360 **kwargs): |
349 """ | 361 """ |
350 Connect to a Walrus service. | 362 Connect to a Walrus service. |
351 | 363 |
352 :type host: string | 364 :type host: string |
353 :param host: the host name or ip address of the Walrus server | 365 :param host: the host name or ip address of the Walrus server |
354 | 366 |
355 :type aws_access_key_id: string | 367 :type aws_access_key_id: string |
356 :param aws_access_key_id: Your AWS Access Key ID | 368 :param aws_access_key_id: Your AWS Access Key ID |
357 | 369 |
358 :type aws_secret_access_key: string | 370 :type aws_secret_access_key: string |
359 :param aws_secret_access_key: Your AWS Secret Access Key | 371 :param aws_secret_access_key: Your AWS Secret Access Key |
360 | 372 |
361 :rtype: :class:`boto.s3.connection.S3Connection` | 373 :rtype: :class:`boto.s3.connection.S3Connection` |
362 :return: A connection to Walrus | 374 :return: A connection to Walrus |
363 """ | 375 """ |
364 from boto.s3.connection import S3Connection | 376 from boto.s3.connection import S3Connection |
365 from boto.s3.connection import OrdinaryCallingFormat | 377 from boto.s3.connection import OrdinaryCallingFormat |
366 | 378 |
| 379 # Check for values in boto config, if not supplied as args |
| 380 if not aws_access_key_id: |
| 381 aws_access_key_id = config.get('Credentials', |
| 382 'euca_access_key_id', |
| 383 None) |
| 384 if not aws_secret_access_key: |
| 385 aws_secret_access_key = config.get('Credentials', |
| 386 'euca_secret_access_key', |
| 387 None) |
| 388 if not host: |
| 389 host = config.get('Boto', 'walrus_host', None) |
| 390 |
367 return S3Connection(aws_access_key_id, aws_secret_access_key, | 391 return S3Connection(aws_access_key_id, aws_secret_access_key, |
368 host=host, port=port, path=path, | 392 host=host, port=port, path=path, |
369 calling_format=OrdinaryCallingFormat(), | 393 calling_format=OrdinaryCallingFormat(), |
370 is_secure=is_secure, **kwargs) | 394 is_secure=is_secure, **kwargs) |
371 | 395 |
372 def connect_ses(aws_access_key_id=None, aws_secret_access_key=None, **kwargs): | 396 def connect_ses(aws_access_key_id=None, aws_secret_access_key=None, **kwargs): |
373 """ | 397 """ |
374 :type aws_access_key_id: string | 398 :type aws_access_key_id: string |
375 :param aws_access_key_id: Your AWS Access Key ID | 399 :param aws_access_key_id: Your AWS Access Key ID |
376 | 400 |
377 :type aws_secret_access_key: string | 401 :type aws_secret_access_key: string |
378 :param aws_secret_access_key: Your AWS Secret Access Key | 402 :param aws_secret_access_key: Your AWS Secret Access Key |
379 | 403 |
380 :rtype: :class:`boto.ses.SESConnection` | 404 :rtype: :class:`boto.ses.SESConnection` |
381 :return: A connection to Amazon's SES | 405 :return: A connection to Amazon's SES |
382 """ | 406 """ |
383 from boto.ses import SESConnection | 407 from boto.ses import SESConnection |
384 return SESConnection(aws_access_key_id, aws_secret_access_key, **kwargs) | 408 return SESConnection(aws_access_key_id, aws_secret_access_key, **kwargs) |
385 | 409 |
| 410 def connect_sts(aws_access_key_id=None, aws_secret_access_key=None, **kwargs): |
| 411 """ |
| 412 :type aws_access_key_id: string |
| 413 :param aws_access_key_id: Your AWS Access Key ID |
| 414 |
| 415 :type aws_secret_access_key: string |
| 416 :param aws_secret_access_key: Your AWS Secret Access Key |
| 417 |
| 418 :rtype: :class:`boto.sts.STSConnection` |
| 419 :return: A connection to Amazon's STS |
| 420 """ |
| 421 from boto.sts import STSConnection |
| 422 return STSConnection(aws_access_key_id, aws_secret_access_key, **kwargs) |
| 423 |
386 def connect_ia(ia_access_key_id=None, ia_secret_access_key=None, | 424 def connect_ia(ia_access_key_id=None, ia_secret_access_key=None, |
387 is_secure=False, **kwargs): | 425 is_secure=False, **kwargs): |
388 """ | 426 """ |
389 Connect to the Internet Archive via their S3-like API. | 427 Connect to the Internet Archive via their S3-like API. |
390 | 428 |
391 :type ia_access_key_id: string | 429 :type ia_access_key_id: string |
392 :param ia_access_key_id: Your IA Access Key ID. This will also look in your | 430 :param ia_access_key_id: Your IA Access Key ID. This will also look in your |
393 boto config file for an entry in the Credentials | 431 boto config file for an entry in the Credentials |
394 section called "ia_access_key_id" | 432 section called "ia_access_key_id" |
395 | 433 |
396 :type ia_secret_access_key: string | 434 :type ia_secret_access_key: string |
397 :param ia_secret_access_key: Your IA Secret Access Key. This will also look
in your | 435 :param ia_secret_access_key: Your IA Secret Access Key. This will also |
398 boto config file for an entry in the Credential
s | 436 look in your boto config file for an entry |
399 section called "ia_secret_access_key" | 437 in the Credentials section called |
| 438 "ia_secret_access_key" |
400 | 439 |
401 :rtype: :class:`boto.s3.connection.S3Connection` | 440 :rtype: :class:`boto.s3.connection.S3Connection` |
402 :return: A connection to the Internet Archive | 441 :return: A connection to the Internet Archive |
403 """ | 442 """ |
404 from boto.s3.connection import S3Connection | 443 from boto.s3.connection import S3Connection |
405 from boto.s3.connection import OrdinaryCallingFormat | 444 from boto.s3.connection import OrdinaryCallingFormat |
406 | 445 |
407 access_key = config.get('Credentials', 'ia_access_key_id', | 446 access_key = config.get('Credentials', 'ia_access_key_id', |
408 ia_access_key_id) | 447 ia_access_key_id) |
409 secret_key = config.get('Credentials', 'ia_secret_access_key', | 448 secret_key = config.get('Credentials', 'ia_secret_access_key', |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
499 path = uri_str | 538 path = uri_str |
500 else: | 539 else: |
501 scheme = uri_str[0:end_scheme_idx].lower() | 540 scheme = uri_str[0:end_scheme_idx].lower() |
502 path = uri_str[end_scheme_idx + 3:] | 541 path = uri_str[end_scheme_idx + 3:] |
503 | 542 |
504 if scheme not in ['file', 's3', 'gs']: | 543 if scheme not in ['file', 's3', 'gs']: |
505 raise InvalidUriError('Unrecognized scheme "%s"' % scheme) | 544 raise InvalidUriError('Unrecognized scheme "%s"' % scheme) |
506 if scheme == 'file': | 545 if scheme == 'file': |
507 # For file URIs we have no bucket name, and use the complete path | 546 # For file URIs we have no bucket name, and use the complete path |
508 # (minus 'file://') as the object name. | 547 # (minus 'file://') as the object name. |
509 return FileStorageUri(path, debug) | 548 is_stream = False |
| 549 if path == '-': |
| 550 is_stream = True |
| 551 return FileStorageUri(path, debug, is_stream) |
510 else: | 552 else: |
511 path_parts = path.split('/', 1) | 553 path_parts = path.split('/', 1) |
512 bucket_name = path_parts[0] | 554 bucket_name = path_parts[0] |
513 if (validate and bucket_name and | 555 if (validate and bucket_name and |
514 # Disallow buckets violating charset or not [3..255] chars total. | 556 # Disallow buckets violating charset or not [3..255] chars total. |
515 (not re.match('^[a-z0-9][a-z0-9\._-]{1,253}[a-z0-9]$', bucket_name) | 557 (not re.match('^[a-z0-9][a-z0-9\._-]{1,253}[a-z0-9]$', bucket_name) |
516 # Disallow buckets with individual DNS labels longer than 63. | 558 # Disallow buckets with individual DNS labels longer than 63. |
517 or re.search('[-_a-z0-9]{64}', bucket_name))): | 559 or re.search('[-_a-z0-9]{64}', bucket_name))): |
518 raise InvalidUriError('Invalid bucket name in URI "%s"' % uri_str) | 560 raise InvalidUriError('Invalid bucket name in URI "%s"' % uri_str) |
519 # If enabled, ensure the bucket name is valid, to avoid possibly | 561 # If enabled, ensure the bucket name is valid, to avoid possibly |
(...skipping 13 matching lines...) Expand all Loading... |
533 :param key: URI naming bucket + optional object. | 575 :param key: URI naming bucket + optional object. |
534 """ | 576 """ |
535 if not isinstance(key, boto.s3.key.Key): | 577 if not isinstance(key, boto.s3.key.Key): |
536 raise InvalidUriError('Requested key (%s) is not a subclass of ' | 578 raise InvalidUriError('Requested key (%s) is not a subclass of ' |
537 'boto.s3.key.Key' % str(type(key))) | 579 'boto.s3.key.Key' % str(type(key))) |
538 prov_name = key.bucket.connection.provider.get_provider_name() | 580 prov_name = key.bucket.connection.provider.get_provider_name() |
539 uri_str = '%s://%s/%s' % (prov_name, key.bucket.name, key.name) | 581 uri_str = '%s://%s/%s' % (prov_name, key.bucket.name, key.name) |
540 return storage_uri(uri_str) | 582 return storage_uri(uri_str) |
541 | 583 |
542 boto.plugin.load_plugins(config) | 584 boto.plugin.load_plugins(config) |
OLD | NEW |