object_storage.rst 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. Working with object storage
  2. ===========================
  3. Object storage provides a simple way to store and retrieve large amounts of
  4. unstructured data over HTTP. Object Storage is also referred to as Blob (Binary
  5. Large OBject) Storage by Azure, and Simple Storage Service (S3) by Amazon.
  6. Typically, you would store your objects within a Bucket, as it is known in
  7. AWS and GCP. A Bucket is also called a Container in OpenStack and Azure. In
  8. CloudBridge, we use the term Bucket.
  9. Storing objects in a bucket
  10. ---------------------------
  11. To store an object within a bucket, we need to first create a bucket or
  12. retrieve an existing bucket.
  13. .. code-block:: python
  14. bucket = provider.storage.buckets.create('my-bucket')
  15. bucket.objects.list()
  16. Next, let's upload some data to this bucket. To efficiently upload a file,
  17. simple use the upload_from_file method.
  18. .. code-block:: python
  19. obj = bucket.objects.create('my-data.txt')
  20. obj.upload_from_file('/path/to/myfile.txt')
  21. You can also use the upload() function to upload from an in memory stream.
  22. Note that, an object you create with objects.create() doesn't actually get
  23. persisted until you upload some content.
  24. To locate and download this uploaded file again, you can do the following:
  25. .. code-block:: python
  26. bucket = provider.storage.buckets.find(name='my-bucket')[0]
  27. obj = bucket.objects.find(name='my-data.txt')[0]
  28. print("Size: {0}, Modified: {1}".format(obj.size, obj.last_modified))
  29. with open('/tmp/myfile.txt', 'wb') as f:
  30. obj.save_content(f)
  31. To download to a local path, prefer download_to_file(), which fetches large
  32. objects as parallel ranged reads. save_content() and iter_content() are the
  33. single-stream alternatives, for writing to an arbitrary stream or for handing
  34. the content on somewhere else - proxying it to an HTTP response, say.
  35. .. code-block:: python
  36. for chunk in obj.iter_content():
  37. process(chunk)
  38. Content is streamed, never held in memory whole, and chunks are sized by
  39. chunk_size rather than by the content - binary data is never split on
  40. newlines. Only the last chunk may be short.
  41. .. code-block:: python
  42. for chunk in obj.iter_content(chunk_size=4 * 1024 * 1024):
  43. process(chunk)
  44. chunk_size defaults to 1 MiB, which suits most callers. It trades per-chunk
  45. overhead against memory and latency: each chunk costs a read from the provider
  46. plus whatever your loop does per chunk, so small values get expensive over a
  47. large object, while a large value is buffered in full before it is yielded and
  48. so costs memory per concurrent stream. To change the default globally, set the
  49. iter_chunk_size provider config value or the CB_ITER_CHUNK_SIZE environment
  50. variable. save_content() takes the same argument.
  51. .. note::
  52. On GCP the content is fetched as successive ranged requests, because the
  53. underlying client library has no single-connection streaming read, so
  54. chunk_size is also the request size there. Prefer a large chunk_size when
  55. streaming a large object from GCP.
  56. Using tokens for authentication
  57. -------------------------------
  58. Some providers may support using temporary credentials with a session token,
  59. in which case you will be able to access a particular bucket by using that
  60. session token.
  61. .. code-block:: python
  62. provider = CloudProviderFactory().create_provider(
  63. ProviderList.AWS,
  64. {'aws_access_key': 'ACCESS_KEY',
  65. 'aws_secret_key': 'SECRET_KEY',
  66. 'aws_session_token': 'MY_SESSION_TOKEN'})
  67. .. code-block:: python
  68. provider = CloudProviderFactory().create_provider(
  69. ProviderList.OPENSTACK,
  70. {'os_storage_url': 'SWIFT_STORAGE_URL',
  71. 'os_auth_token': 'MY_SESSION_TOKEN'})
  72. Once a provider is obtained, you can access the container as usual:
  73. .. code-block:: python
  74. bucket = provider.storage.buckets.get(container)
  75. obj = bucket.objects.create('my_object.txt')
  76. obj.upload_from_file(source)
  77. Generating signed URLs
  78. ----------------------
  79. Signed URLs are a great way to allow users who do not have credentials for
  80. the cloud provider of your choice, to interact with an object within a
  81. storage bucket.
  82. You can generate signed URLs with ``GET`` permissions to allow a user to
  83. get an object.
  84. .. code-block:: python
  85. provider = CloudProviderFactory().create_provider(
  86. ProviderList.AWS,
  87. {'aws_access_key': 'ACCESS_KEY',
  88. 'aws_secret_key': 'SECRET_KEY',
  89. 'aws_session_token': 'MY_SESSION_TOKEN'})
  90. bucket = provider.storage.buckets.get("my-bucket")
  91. obj = bucket.objects.get("my-file.txt")
  92. url = obj.generate_url(expires_in=7200)
  93. You can also generate a signed URL with `PUT` permissions to allow users
  94. to upload files to your storage bucket.
  95. .. code-block:: python
  96. provider = CloudProviderFactory().create_provider(
  97. ProviderList.AWS,
  98. {'aws_access_key': 'ACCESS_KEY',
  99. 'aws_secret_key': 'SECRET_KEY',
  100. 'aws_session_token': 'MY_SESSION_TOKEN'})
  101. bucket = provider.storage.buckets.get("my-bucket")
  102. obj = bucket.objects.create("my-file.txt")
  103. url = obj.generate_url(expires_in=7200, writable=True)
  104. With your signed URL, you or someone on your team can upload a file like this
  105. .. code-block:: python
  106. import requests
  107. content = b"Hello world!"
  108. # Only Azure requires the x-ms-blob-type header to be present, but there's no harm
  109. # in sending this in for all providers.
  110. headers = {'x-ms-blob-type': 'BlockBlob'}
  111. requests.put(url, data=content)