Remarques :

Utiliser Oracle Cloud Infrastructure Object Storage Service avec l'API Swift OpenStack

Introduction

Oracle Cloud Infrastructure (OCI) Object Storage est une architecture de stockage de données qui gère et organise les informations numériques en tant qu'objets, comprenant chacun des données, des métadonnées et un identificateur unique. Contrairement au stockage de fichiers ou de blocs traditionnel, OCI Object Storage ne s'appuie pas sur une structure hiérarchique, ce qui permet une gestion efficace et évolutive de grandes quantités de données non structurées. Les objets sont stockés dans un espace d'adressage plat, ce qui simplifie l'extraction des données et permet une évolutivité transparente. Cette solution est idéale pour divers types de données, tels que le contenu multimédia et les sauvegardes, ce qui en fait un choix robuste pour les environnements cloud, le stockage d'archives et les systèmes distribués en raison de sa flexibilité, de sa durabilité et de sa facilité d'accès. Les utilisateurs interagissent avec le service de stockage d'objets à l'aide d'une interface REST via le protocole HTTP.

Le service OCI Object Storage est une solution de stockage cloud dans laquelle Oracle gère la complexité de la gestion, garantissant une durabilité des données fiable et rentable. L'élasticité de la plate-forme permet un démarrage progressif avec la possibilité d'évoluer de manière transparente, le tout sans compromettre les performances ou la fiabilité du service.

OCI Object Storage offre une compatibilité d'API avec l'API Swift OpenStack et le service Amazon Simple Storage (Amazon S3) via l'API de compatibilité Amazon S3. Cela permet aux clients de continuer à utiliser leurs outils existants (par exemple, les clients SDK), ce qui réduit la nécessité d'apporter des modifications à leurs applications. Pour plus d'informations, reportez-vous à API de compatibilité Amazon S3. Ce tutoriel se concentrera sur la consommation d'API compatible avec OCI OpenStack Swift.

Avant de commencer à discuter de l'API Swift OpenStack, nous devons clarifier certaines des structures utilisées dans OCI Object Storage.

OpenStack Swift définit trois structures : Compte, Conteneur et Objet.

Nous pouvons désormais identifier des ressources équivalentes entre OCI Object Storage et l'API Swift OpenStack.

Objectifs

Prérequis

Utiliser l'API OCI Swift

Les adresses régionales de l'API OCI Swift utilisent un format d'URL cohérent de https://swiftobjectstorage.<region-identifier>.oraclecloud.com. Par exemple, l'adresse d'API OCI Swift native dans la région Est des Etats-Unis (US-ashburn-1) est https://swiftobjectstorage.US-ashburn-1.oraclecloud.com.

Compte tenu de l'isolement au niveau du locataire au niveau de la région, l'adresse d'API OCI Swift devient : https://swiftobjectstorage.<region-identifier>.oraclecloud.com/<tenancy-namespace>, où <tenancy-namespace> est la chaîne d'espace de noms Object Storage générée automatiquement de la location dans laquelle créer des référentiels. Pour plus d'informations, reportez-vous à Page Informations sur la location.

L'API Swift OCI ne dispose pas du concept de compartiment. Par défaut, les compartiments créés à l'aide de l'API de compatibilité Amazon S3 OCI ou de l'API Swift OCI sont créés dans le compartiment root de la location Oracle Cloud Infrastructure. Vous pouvez désigner un autre compartiment pour que l'API de compatibilité Amazon S3 OCI ou l'API Swift OCI crée des buckets. Pour plus d'informations, reportez-vous à Modification des désignations de compartiment pour l'API de compatibilité Amazon S3 et l'API Swift d'une location.

L'API OCI Swift prend en charge trois approches pour authentifier les demandes.

Approche 1 : Utiliser l'en-tête d'autorisation de base

Le nom utilisateur a le format <username>. Par exemple, john.doe@acme.com. Si votre location est fédérée avec Oracle Identity Cloud Service, utilisez le format oracleidentitycloudservice/<username>.

Le mot de passe est le jeton d'authentification généré pour l'utilisateur. Par exemple, my-auth-token. Pour plus d'informations, reportez-vous à obtention d'un jeton d'authentification.

Chaque demande adressée à l'API OCI Swift doit inclure l'en-tête suivant.

Par exemple, si le nom utilisateur est oracleidentitycloudservice/john.doe@acme.com et le mot de passe est my-auth-token, l'en-tête se présente comme suit :

Nous utiliserons certains des appels d'API décrits dans la documentation officielle. Reportez-vous à OpenStack Swift API.

Exemple :

  1. Initialisez les variables d'environnement requises suivantes.

    user='<username>'
    password='<password>'
    region='<oci-region>'
    tenancy_namespace='<tenancy-namespace>'
    bucket_name='tutorial-bucket'
    object_name='sample.txt'
    
  2. Répertoriez les buckets du compte. Seuls les buckets des compartiments d'API OCI Swift sélectionnés sont répertoriés.

    curl -sS -D /dev/stderr "https://swiftobjectstorage.${region}.oraclecloud.com/v1/${tenancy_namespace}" -u "${user}:${password}" | jq
    
  3. Création d'un bucket.

    curl -sS -i "https://swiftobjectstorage.${region}.oraclecloud.com/v1/${tenancy_namespace}/${bucket_name}" -X PUT -u "${user}:${password}"
    
  4. Téléchargez un fichier vers le bucket.

    echo 'sample file' > ${object_name}
    curl -s -i "https://swiftobjectstorage.${region}.oraclecloud.com/v1/${tenancy_namespace}/${bucket_name}/${object_name}" -X PUT --data-binary "@${object_name}" -u "${user}:${password}"
    
  5. Répertoriez le contenu du bucket.

    curl -sS -D /dev/stderr "https://swiftobjectstorage.${region}.oraclecloud.com/v1/${tenancy_namespace}/${bucket_name}" -u "${user}:${password}" | jq
    
  6. Extrayez un fichier à partir du bucket.

    curl -s -D /dev/stderr "https://swiftobjectstorage.${region}.oraclecloud.com/v1/${tenancy_namespace}/${bucket_name}/${object_name}" -u "${user}:${password}" -o downloaded_file.txt
    cat downloaded_file.txt
    
  7. Supprimez le fichier du bucket.

    curl -sS -i "https://swiftobjectstorage.${region}.oraclecloud.com/v1/${tenancy_namespace}/${bucket_name}/${object_name}" -X DELETE -u "${user}:${password}"
    
  8. Supprimez le bucket.

    curl -s -i "https://swiftobjectstorage.${region}.oraclecloud.com/v1/${tenancy_namespace}/${bucket_name}" -X DELETE -u "${user}:${password}"
    

Approche 2 : authentification par jeton à l'aide de l'authentification v1

Vous devrez appeler l'adresse d'autorisation d'API Swift OCI pour la région et inclure les en-têtes X-Storage-User et X-Storage-Pass dans la demande. Si la demande d'authentification réussit, vous recevrez une réponse avec l'en-tête X-Storage-Token qui peut être utilisé pour l'autorisation de demande et l'en-tête X-Storage-Url avec l'adresse d'API OCI Swift pour le compte.

L'en-tête X-Storage-User a le format <tenancy-namespace>:<username>.

Par exemple, si tenancy-namespace est axaxnpcrorw5 et que le nom utilisateur est identique à l'approche 1, la valeur de l'en-tête est axaxnpcrorw5:oracleidentitycloudservice/john.doe@acme.com.

X-Storage-Pass est le jeton d'authentification généré.

Exemple :

  1. Initialisez les variables d'environnement requises suivantes.

    user='<username>'
    password='<password>'
    region='<oci-region>'
    tenancy_namespace='<tenancy-namespace>'
    bucket_name='tutorial-bucket'
    object_name='sample.txt'
    
  2. Générer un jeton.

    curl -sS -D swift_headers.txt https://swiftobjectstorage.eu-frankfurt-1.oraclecloud.com/auth/v1.0 -H "X-Storage-User: ${tenancy_namespace}:${user}" -H "X-Storage-Pass: ${password}"
    X_Auth_Token=$(cat swift_headers.txt | grep X-Auth-Token | cut -d":" -f 2)
    
  3. Répertoriez les buckets du compte. Seuls les buckets des compartiments d'API OCI Swift sélectionnés sont répertoriés.

    curl -s -D /dev/stderr "https://swiftobjectstorage.${region}.oraclecloud.com/v1/${tenancy_namespace}" -H "X-Auth-Token: ${X_Auth_Token}" | jq
    
  4. Création d'un bucket.

    curl -s -i "https://swiftobjectstorage.${region}.oraclecloud.com/v1/${tenancy_namespace}/${bucket_name}" -X PUT -H "X-Auth-Token: ${X_Auth_Token}"
    
  5. Téléchargez un fichier vers le bucket.

    echo 'sample file' > ${object_name}
    curl -s -i "https://swiftobjectstorage.${region}.oraclecloud.com/v1/${tenancy_namespace}/${bucket_name}/${object_name}" -X PUT --data-binary "@${object_name}" -H "X-Auth-Token: ${X_Auth_Token}"
    
  6. Répertoriez le contenu du bucket.

    curl -s -D /dev/stderr "https://swiftobjectstorage.${region}.oraclecloud.com/v1/${tenancy_namespace}/${bucket_name}" -H "X-Auth-Token: ${X_Auth_Token}" | jq
    
  7. Extrayez un fichier à partir du bucket.

    curl -s -D /dev/stderr "https://swiftobjectstorage.${region}.oraclecloud.com/v1/${tenancy_namespace}/${bucket_name}/${object_name}" -H "X-Auth-Token: ${X_Auth_Token}" -o downloaded_file.txt
    cat downloaded_file.txt
    
  8. Supprimez le fichier du bucket.

    curl -s -i "https://swiftobjectstorage.${region}.oraclecloud.com/v1/${tenancy_namespace}/${bucket_name}/${object_name}" -X DELETE -H "X-Auth-Token: ${X_Auth_Token}"
    
  9. Supprimez le bucket.

    curl -s -i "https://swiftobjectstorage.${region}.oraclecloud.com/v1/${tenancy_namespace}/${bucket_name}" -X DELETE -H "X-Auth-Token: ${X_Auth_Token}"
    

Approche 3 : authentification par jeton à l'aide de l'authentification v2

Pour illustrer la procédure d'autorisation v2 de l'API OCI Swift, nous utiliserons le package Python officiel de l'API Swift OpenStack python-swiftclient 4.5.0, ainsi que les dépendances requises pour l'authentification v2 python-keystoneclient 5.4.0.

Exemple :

  1. Exécutez la commande suivante pour vous assurer que vous avez accès à une version de Python supérieure à 3.6. Pour plus d'informations, voir Télécharger Python.

    python3 --version
    
  2. Installez les modules Python requis.

    python3 -m pip install python-swiftclient python-keystoneclient click
    
  3. Vous pouvez utiliser le code suivant pour interagir avec l'API OCI Swift v2. Veillez à remplacer les espaces réservés pour <user>, <password>, <region> et <tenancy-namespace> dans le code suivant avant l'exécution.

    import click
    import os
    
    from swiftclient.client import Connection
    from swiftclient.exceptions import ClientException
    
    user='<username>'
    password='<password>'
    region='<oci-region>'
    tenancy_namespace='<tenancy-namespace>'
    bucket_name='tutorial-bucket'
    object_name='sample.txt'
    
    _authurl = f'https://swiftobjectstorage.{region}.oraclecloud.com/auth/v2.0/'
    _auth_version = '2'
    _user = f'{user}'
    _key = f'{password}'
    _tenant_name = f'{tenancy_namespace}'
    
    conn = Connection(
        authurl=_authurl,
        user=_user,
        key=_key,
        tenant_name=_tenant_name,
        auth_version=_auth_version
    )
    
    @click.group(invoke_without_command=True)
    @click.pass_context
    def main(ctx):
        available_commands = {
            "a": ("List buckets in the account", get_account),
            "b": ("Create a new bucket", put_container),
            "c": ("Upload an object to the bucket", put_object),
            "d": ("List objects in the bucket", get_container),
            "e": ("Download object from the bucket", get_object),
            "f": ("Delete object from the bucket", delete_object),
            "g": ("Delete bucket from the account", delete_container)
        }
        while True:
            click.echo("Available actions")
            for index, command in available_commands.items():
                click.echo(f"{index} - {command[0]}")
            action = click.prompt("Please select an option from the list")
            if action in available_commands.keys():
                ctx.invoke(available_commands[action][1])
            print("###"*10)
    
    @main.command()
    def get_account(conn=conn):
        print("Listing buckets in the account.")
        try:
            resp_headers = conn.get_account()
            for entry in resp_headers[1]:
                print(entry["name"])
        except ClientException as e:
            print(f"Failed to get the buckets in the tenancy. Error: {e}")
            raise
        else:
            print(f"Successfuly listed bucket in the '{_tenant_name}' account.")
    
    @main.command()
    def put_container(conn=conn, bucket_name=bucket_name):
        print(f"Creating a new bucket named {bucket_name}.")
        try:
            resp_headers = conn.put_container(container=bucket_name)
        except ClientException as e:
            print(f"Failed to create the new bucket named {bucket_name} in the tenancy. Error: {e}")
            raise
        else:
            print(f"The '{bucket_name}' was successfuly created.")
    
    @main.command()
    def put_object(conn=conn, bucket_name=bucket_name, object_name=object_name):
        print(f"Uploading a new file, '{object_name}' to the new bucket '{bucket_name}'.")
        try:
            if not os.path.isfile(object_name):
                with open(object_name, "w") as f:
                    f.write("sample file")
            with open(object_name) as f:
                resp_headers = conn.put_object(container=bucket_name, obj=object_name, contents=object_name)
        except ClientException as e:
            print(f"Failed to create a new object named '{object_name}' in the bucket '{bucket_name}'. Error: {e}")
            raise
        else:
            print(f"The '{object_name}' file was successfuly uploaded to '{bucket_name}' bucket.")
    
    @main.command()
    def get_container(conn=conn, bucket_name=bucket_name):
        print(f"List {bucket_name} bucket contents.")
        try:
            resp_headers = conn.get_container(container=bucket_name)
            for entry in resp_headers[1]:
                print(entry["name"])
        except ClientException as e:
            print(f"Failed to list objects in the bucket {bucket_name}. Error: {e}")
            raise
        else:
            print(f"The '{bucket_name}' content was successfuly listed.")
    
    @main.command()
    def get_object(conn=conn, bucket_name=bucket_name, object_name=object_name, dest_file="downloaded_file.txt"):
        print(f"Fetch {object_name} object from the bucket {bucket_name}.")
        try:
            resp_headers = conn.get_object(container=bucket_name, obj=object_name)
            with open(dest_file, "wb") as f:
                f.write(resp_headers[1])
        except ClientException as e:
            print(f"Failed to download {object_name} from {bucket_name} to local file named '{dest_file}'. Error: {e}")
            raise
        else:
            print(f"The '{object_name}' object was saved locally to '{dest_file}'.")
    
    @main.command()
    def delete_object(conn=conn, bucket_name=bucket_name, object_name=object_name):
        print(f"Deleting {object_name} object from the bucket {bucket_name}.")
        try:
            resp_headers = conn.delete_object(container=bucket_name, obj=object_name)
        except ClientException as e:
            print(f"Failed to delete {object_name} from {bucket_name}. Error: {e}")
            raise
        else:
            print(f"The '{object_name}' object was deleted.")
    
    @main.command()
    def delete_container(conn=conn, bucket_name=bucket_name):
        print(f"Deleting the bucket {bucket_name}.")
        try:
            resp_headers = conn.delete_container(container=bucket_name)
        except ClientException as e:
            print(f"Failed to delete {object_name} from {bucket_name}. Error: {e}")
            raise
        else:
            print(f"The '{bucket_name}' bucket was deleted.")
    
    
    if __name__ == "__main__":
        main()
    

Remerciements

Ressources de formation supplémentaires

Parcourez d'autres ateliers sur docs.oracle.com/learn ou accédez à davantage de contenus de formation gratuits sur le canal Oracle Learning YouTube. De plus, rendez-vous sur education.oracle.com/learning-explorer pour devenir un explorateur Oracle Learning.

Pour obtenir de la documentation sur le produit, visitez Oracle Help Center.