Note :

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

Présentation

Le service de stockage d'objets pour Oracle Cloud Infrastructure (OCI) est une architecture de stockage de données qui gère et organise les informations numériques en tant qu'objets, comprenant chacune des données, des métadonnées et un identificateur unique. Contrairement au stockage de fichiers ou par blocs traditionnel, le service de stockage d'objets d'OCI ne repose pas sur une structure hiérarchique, ce qui permet un traitement efficace et évolutif de grandes quantités de données non structurées. Les objets sont stockés dans un espace d'adresses 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 en nuage, 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 sur le protocole HTTP.

Le service de stockage d'objets d'OCI est une solution de stockage en nuage où Oracle gère la complexité de la gestion, assurant ainsi 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.

Le service de stockage d'objets pour OCI assure la compatibilité de l'API avec l'OpenStack API Swift et le service Amazon Simple Storage (Amazon S3) au moyen de 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 le besoin d'apporter des modifications à leurs applications. Pour plus d'informations, voir API de compatibilité Amazon S3. Ce tutoriel se concentrera sur l'utilisation de l'API compatible avec Swift pour OCI OpenStack.

Avant de commencer à discuter de l'API Swift OpenStack, nous devons clarifier certaines des structures utilisées dans le stockage d'objets OCI.

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

Nous pouvons maintenant identifier des ressources équivalentes entre le stockage d'objets OCI et l'API Swift OpenStack.

Objectifs

Préalables

Utiliser l'API Swift OCI

Les points d'extrémité régionaux de l'API Swift pour OCI utilisent un format d'URL cohérent de https://swiftobjectstorage.<region-identifier>.oraclecloud.com. Par exemple, le point d'extrémité d'API Swift OCI natif dans la région États-Unis - Est (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, le point d'extrémité de l'API Swift pour OCI devient : https://swiftobjectstorage.<region-identifier>.oraclecloud.com/<tenancy-namespace>, où <tenancy-namespace> est la chaîne d'espace de noms du stockage d'objets générée automatiquement de la location dans laquelle créer des référentiels. Pour plus d'informations, consultez la page Informations sur la location.

L'API Swift pour OCI n'a pas le concept de compartiment. Par défaut, les seaux créés à l'aide de l'API de compatibilité Amazon S3 d'OCI ou de l'API Swift OCI sont créés dans le compartiment racine de la location Oracle Cloud Infrastructure. Vous pouvez désigner un compartiment différent pour l'API de compatibilité Amazon S3 d'OCI ou l'API Swift d'OCI pour créer des compartiments. Pour plus d'informations, voir Modification des désignations de compartiment de l'API de compatibilité Amazon S3 et de l'API Swift de la location.

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

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

Le nom d'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, voir Obtention d'un jeton d'authentification

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

Par exemple, si le nom d'utilisateur est oracleidentitycloudservice/john.doe@acme.com et le mot de passe est my-auth-token, l'en-tête ressemblera à :

Nous utiliserons certains des appels d'API décrits dans la documentation officielle. Voir OpenStack API Swift.

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. Lister les seaux du compte. Seuls les seaux des compartiments d'API Swift OCI sélectionnés seront listés.

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

    curl -sS -i "https://swiftobjectstorage.${region}.oraclecloud.com/v1/${tenancy_namespace}/${bucket_name}" -X PUT -u "${user}:${password}"
    
  4. Chargez un fichier dans le seau.

    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 seau.

    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 seau.

    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 seau.

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

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

Approche 2 : Authentification basée sur un jeton à l'aide de v1 Authentification

Vous devrez appeler le point d'extrémité d'autorisation de l'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 la demande, et l'en-tête X-Storage-Url avec le point d'extrémité de l'API Swift OCI 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 d'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. Lister les seaux du compte. Seuls les seaux des compartiments d'API Swift OCI sélectionnés seront listés.

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

    curl -s -i "https://swiftobjectstorage.${region}.oraclecloud.com/v1/${tenancy_namespace}/${bucket_name}" -X PUT -H "X-Auth-Token: ${X_Auth_Token}"
    
  5. Chargez un fichier dans le seau.

    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 seau.

    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 seau.

    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 seau.

    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. Supprimer le seau.

    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 basée sur un jeton à l'aide de v2 Authentification

Pour illustrer la procédure d'autorisation v2 de l'API Swift pour OCI, nous utiliserons l'ensemble Python OpenStack Swift API python-swiftclient 4.5.0 et 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 au-dessus de 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 Swift d'OCI v2. Assurez-vous de remplacer les paramètres fictifs 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()
    

Confirmation

Autres ressources d'apprentissage

Explorez d'autres laboratoires sur la page docs.oracle.com/learn ou accédez à plus de contenu d'apprentissage gratuit sur le canal YouTube d'Oracle Learning. De plus, visitez education.oracle.com/learning-explorer pour devenir un explorateur Oracle Learning.

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