Skip to content

Introduction

Object Storage offers a scalable storage service which can be used by applications using HTTP or the S3 protocol.
It is ideal for storing unstructured data (called "blob" or "objects") such as documents, images, large binary files...

The Infomaniak Object Stores are built upon Swift.

Main features

  • Guarantees data availability, durability and consistency
  • Files can be sent using the dashboard or via an API
  • Unlimited storage capacity
  • Containers are private by default but can be public

Technical details

  • Files are stored in containers
  • The name of each container must be unique in the project
  • The upload is limited to :
    • 5Gb per file via the dashboard
    • 50Tb via API (multi-threading DLO/SLO)
  • A successful file upload returns an HTTP 200 code

Display capabilities

To know enabled plugins (middlewares) on our cluster, you can use:

swift capabilities

Using Swift Object Storage

Some commands are not available through the OpenStackClient. We will install the Swift Client.

pip install python3-swiftclient

Create a container:

I'll create a container named public:

openstack container create public
+---------------------------------------+-----------+------------------------------------+
| account                               | container | x-trans-id                         |
+---------------------------------------+-----------+------------------------------------+
| AUTH_d1440xxxxxxxxxxxxxxxxxxxxxxxxxxx | public    | tx59c2735e9bfd4a5181079-006048ddc8 |
+---------------------------------------+-----------+------------------------------------+

List your containers:

openstack container list 
+--------+
| Name   |
+--------+
| public |
+--------+

Store an object:

openstack object create --name 'eBooks/Cuisine/Les Crêpes du Monde.pdf' public '~/Documents/Ebooks/Cuisine/Les Crêpes du Monde.pdf'
+----------------------------------------+-----------+----------------------------------+
| object                                 | container | etag                             |
+----------------------------------------+-----------+----------------------------------+
| eBooks/Cuisine/Les Crêpes du Monde.pdf | public    | a87f8e432d5c0c163d575a7fde411be8 |
+----------------------------------------+-----------+----------------------------------+

The --name option override the final object name.
By default, it uses your local object name.

List your objects:

openstack object list public
+----------------------------------------+
| Name                                   |
+----------------------------------------+
| eBooks/Cuisine/Les Crêpes du Monde.pdf |
+----------------------------------------+

Delete an object:

openstack object delete public 'eBooks/Cuisine/Les Crêpes du Monde.pdf'

Get an authentication token with switf client:

swift auth

or using curl, create a script called get_token.sh with the following content:

#!/bin/sh

TMPFILE=`mktemp`
JSONFILE=`mktemp`

cat >${JSONFILE} <<EOF
{
  "auth": {
    "identity": {
      "methods": ["password"],
      "password": {
        "user": {
          "domain": {"name": "${OS_USER_DOMAIN_NAME}"},
          "name": "${OS_USERNAME}",
          "password": "${OS_PASSWORD}"
        }
      }
    },
    "scope": {
      "project": {
        "domain": {"name": "${OS_PROJECT_DOMAIN_NAME}"},
        "name": "${OS_PROJECT_NAME}"
      }
    }
  }
}
EOF

curl -si  \
  -H "Content-Type: application/json" \
  -o ${TMPFILE} \
  -d @${JSONFILE} \
${OS_AUTH_URL}/auth/tokens 2>/dev/null

tail -1 ${TMPFILE} | jq
grep -i "x-subject-token" ${TMPFILE}

rm -f ${TMPFILE} ${JSONFILE}

Once you have a the access token, you can operate with the Object Storage:

Create a container:

curl -i -X PUT -H "X-Auth-Token: $OS_AUTH_TOKEN" $OS_STORAGE_URL/mycontainer
HTTP/1.1 202 Accepted
content-type: text/html; charset=UTF-8
content-length: 76
x-trans-id: tx1d77854fae534495a2a94-00655c8b2d
x-openstack-request-id: tx1d77854fae534495a2a94-00655c8b2d
date: Tue, 21 Nov 2023 10:49:17 GMT
strict-transport-security: max-age=63072000

<html><h1>Accepted</h1><p>The request is accepted for processing.</p></html>

Upload an object:

curl -i -T my_object -X PUT -H "X-Auth-Token: $OS_AUTH_TOKEN" ${OS_STORAGE_URL}/mycontainer/my_object

Download an object:

curl -S -X GET -H "X-Auth-Token: $OS_AUTH_TOKEN" ${OS_STORAGE_URL}/mycontainer/my_object -O

List containers:

curl -S -X GET -H "X-Auth-Token: $OS_AUTH_TOKEN" ${OS_STORAGE_URL}/

List objects in a container:

curl -S -X GET -H "X-Auth-Token: $OS_AUTH_TOKEN" ${OS_STORAGE_URL}/mycontainer/

Delete an object:

curl -S -X DELETE -H "X-Auth-Token: $OS_AUTH_TOKEN" ${OS_STORAGE_URL}/mycontainer/myobject

Delete a container (must be empty):

curl -S -X DELETE -H "X-Auth-Token: $OS_AUTH_TOKEN" ${OS_STORAGE_URL}/mycontainer

Object versioning

Object Versioning is used to track changes to objects and to enable recovery of specific versions of an object.

Creating a bucket with versioning enabled

swift post -H "X-Versions-Enabled: true" mybucket
curl -i -XPUT -H "X-Auth-Token: ${OS_AUTH_TOKEN}" -H "X-Versions-Enabled: true" ${OS_STORAGE_URL}/mybucket

From now on, each uploaded object will be versioned with an ID. This ID is the timestamp of the upload.

swift upload mybucket object1
swift upload mybucket object1

Listing the objects and available versions

swift list mybucket --versions
183 2023-05-26 07:19:27 1685085567.70333 application/octet-stream object1
183 2023-05-26 07:19:22 1685085562.07717 application/octet-stream object1

Downloading a specific version of an object

swift download mybucket object1 --version-id 1685085562.07717

Deleting a specific version of an object

swift delete mybucket object1 --version-id 1685085567.70333

Note

Deleting a versioned object will only remove the latest version of the object. Older versions are therefore still available.

swift delete mybucket object1
swift list mybucket --versions
0 2023-05-26 07:21:00 1685085660.97534 application/x-deleted;swift_versions_deleted=1 object1
183 2023-05-26 07:20:54 1685085654.97972 application/octet-stream object1
183 2023-05-26 07:19:22 1685085562.07717 application/octet-stream object1

View your account statistics

openstack object store account show
swift list mybucket --versions
+------------+---------------------------------------+
| Field      | Value                                 |
+------------+---------------------------------------+
| Account    | AUTH_d7a1d0xxxxxxxxxxxxxxxxxxxxxxxxxx |
| Bytes      | 9149046                               |
| Containers | 1                                     |
| Objects    | 1                                     |
+------------+---------------------------------------+

Important considerations

An object store is not a filesystem

It cannot be stressed enough that your usage of the object store should reflect the proper use case, and not treat the storage like a traditional filesystem. There are two main restrictions to bear in mind when designing an application that uses an object store:

  • You cannot rename objects. Due to fact that the name of an object is one of the factors that determines where the object and its replicas are stored, renaming would require multiple copies of the data to be moved between physical storage devices. If you want to rename an object you must upload to the new location, or make a server side copy request to the new location, and then delete the original.

  • You cannot modify objects. Objects are stored in multiple locations and are checked for integrity based on the MD5 sum calculated during upload. In order to modify the contents of an object, the entire desired contents must be re-uploaded. In certain special cases it is possible to work around this restriction using large objects, but no general file-like access is available to modify a stored object.

Objects cannot be locked

There is no mechanism to perform a combination of reading the data/metadata from an object and writing an update to that data/metadata in an atomic way. Any user with access to a container could update the contents or metadata associated with an object at any time.

Workflows that assume that no updates have been made since the last read of an object should be discouraged. Enabling a workflow of this type requires an external object locking mechanism and/or cooperation between all clients accessing the data.