Note:

Uso del servicio Oracle Cloud Infrastructure Object Storage con la API de Swift de OpenStack

Introducción

Oracle Cloud Infrastructure (OCI) Object Storage es una arquitectura de almacenamiento de datos que gestiona y organiza la información digital como objetos, cada uno de ellos con datos, metadatos y un identificador único. A diferencia del almacenamiento de bloques o archivos tradicional, OCI Object Storage no se basa en una estructura jerárquica, lo que permite un manejo eficiente y escalable de grandes cantidades de datos no estructurados. Los objetos se almacenan en un espacio de dirección plano, lo que simplifica la recuperación de datos y permite una escalabilidad perfecta. Esta solución es ideal para diversos tipos de datos, como contenido multimedia y copias de seguridad, lo que la convierte en una opción sólida para entornos en la nube, almacenamiento de archivos y sistemas distribuidos debido a su flexibilidad, durabilidad y facilidad de acceso. Los usuarios interactúan con el servicio de almacenamiento de objetos mediante una interfaz REST a través del protocolo HTTP.

El servicio OCI Object Storage es una solución de almacenamiento basada en la nube en la que Oracle gestiona la complejidad de la gestión, garantizando una durabilidad de datos fiable y rentable. La elasticidad de la plataforma permite un inicio gradual con la capacidad de escalar sin problemas, todo sin comprometer el rendimiento o la fiabilidad del servicio.

OCI Object Storage proporciona compatibilidad con la API de OpenStack Swift API y Amazon Simple Storage Service (Amazon S3) a través de la API de compatibilidad de Amazon S3. Esto permite a los clientes seguir utilizando sus herramientas existentes (por ejemplo, clientes de SDK), lo que minimiza la necesidad de realizar cambios en sus aplicaciones. Para obtener más información, consulte API de compatibilidad de Amazon S3. Este tutorial se centrará en el consumo de API compatible con Swift de OCI OpenStack.

Antes de empezar a hablar sobre la API de Swift OpenStack, necesitamos aclarar algunas de las construcciones utilizadas en OCI Object Storage.

Swift de OpenStack define tres construcciones: Account, Container y Object.

Ahora podemos identificar recursos equivalentes entre OCI Object Storage y la API de Swift OpenStack.

Objetivos

Requisitos

Uso de la API de OCI Swift

Los puntos finales regionales de la API de Swift de OCI utilizan un formato de URL consistente de https://swiftobjectstorage.<region-identifier>.oraclecloud.com. Por ejemplo, el punto final nativo de la API de Swift de OCI en la región este de EE. UU. (US-ashburn-1) es https://swiftobjectstorage.US-ashburn-1.oraclecloud.com.

Teniendo en cuenta el aislamiento de nivel de inquilino en el nivel de región, el punto final de la API de Swift de OCI se convierte en: https://swiftobjectstorage.<region-identifier>.oraclecloud.com/<tenancy-namespace>, donde <tenancy-namespace> es la cadena de espacio de nombres de Object Storage generada automáticamente del arrendamiento en el que se van a crear repositorios. Para obtener más información, consulte Página Información de arrendamiento.

La API de OCI Swift carece del concepto de compartimento. Por defecto, los cubos creados mediante la API de compatibilidad de Amazon S3 de OCI o la API de Swift se crean en el compartimento root del arrendamiento de Oracle Cloud Infrastructure. Puede designar un compartimento diferente para que la API de compatibilidad de OCI Amazon S3 o la API de OCI Swift creen cubos. Para obtener más información, consulte Edición de las designaciones de compartimento de la API de compatibilidad de Amazon S3 y la API de Swift del arrendamiento.

La API de OCI Swift admite tres enfoques para autenticar solicitudes.

Enfoque 1: Usar cabecera de autorización básica

El nombre de usuario tiene el formato <username>. Por ejemplo, john.doe@acme.com. Si su arrendamiento está federado con Oracle Identity Cloud Service, utilice el formato oracleidentitycloudservice/<username>.

La contraseña es el token de autenticación generado para el usuario. Por ejemplo, my-auth-token. Para obtener más información, consulte Obtención de un token de autenticación.

Cada solicitud a la API de OCI Swift debe incluir la siguiente cabecera.

Por ejemplo, si el nombre de usuario es oracleidentitycloudservice/john.doe@acme.com y la contraseña es my-auth-token, la cabecera tendrá el siguiente aspecto:

Utilizaremos algunas de las llamadas de API que se describen en la documentación oficial. Consulte OpenStack API de Swift.

Ejemplo:

  1. Inicialice las siguientes variables de entorno necesarias.

    user='<username>'
    password='<password>'
    region='<oci-region>'
    tenancy_namespace='<tenancy-namespace>'
    bucket_name='tutorial-bucket'
    object_name='sample.txt'
    
  2. Muestre los cubos de la cuenta; solo se mostrarán los cubos de los compartimentos seleccionados de la API de OCI Swift.

    curl -sS -D /dev/stderr "https://swiftobjectstorage.${region}.oraclecloud.com/v1/${tenancy_namespace}" -u "${user}:${password}" | jq
    
  3. Creación de un cubo.

    curl -sS -i "https://swiftobjectstorage.${region}.oraclecloud.com/v1/${tenancy_namespace}/${bucket_name}" -X PUT -u "${user}:${password}"
    
  4. Cargue un archivo en el cubo.

    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. Muestre el contenido del cubo.

    curl -sS -D /dev/stderr "https://swiftobjectstorage.${region}.oraclecloud.com/v1/${tenancy_namespace}/${bucket_name}" -u "${user}:${password}" | jq
    
  6. Recupere un archivo del cubo.

    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. Suprima el archivo del cubo.

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

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

Enfoque 2: Autenticación basada en token mediante la autenticación v1

Tendrá que llamar al punto final de autorización de la API de OCI Swift para la región e incluir las cabeceras X-Storage-User y X-Storage-Pass en la solicitud. Si la solicitud de autenticación se realiza correctamente, recibirá una respuesta con la cabecera X-Storage-Token que se puede utilizar para la autorización de solicitudes y la cabecera X-Storage-Url con el punto final de la API de Swift de OCI para la cuenta.

La cabecera X-Storage-User tiene el formato <tenancy-namespace>:<username>.

Por ejemplo, si tenancy-namespace es axaxnpcrorw5 y el nombre de usuario es el mismo que el enfoque 1, el valor de la cabecera es axaxnpcrorw5:oracleidentitycloudservice/john.doe@acme.com.

X-Storage-Pass es el token de autenticación generado.

Ejemplo:

  1. Inicialice las siguientes variables de entorno necesarias.

    user='<username>'
    password='<password>'
    region='<oci-region>'
    tenancy_namespace='<tenancy-namespace>'
    bucket_name='tutorial-bucket'
    object_name='sample.txt'
    
  2. Genere un token.

    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. Muestre los cubos de la cuenta; solo se mostrarán los cubos de los compartimentos seleccionados de la API de OCI Swift.

    curl -s -D /dev/stderr "https://swiftobjectstorage.${region}.oraclecloud.com/v1/${tenancy_namespace}" -H "X-Auth-Token: ${X_Auth_Token}" | jq
    
  4. Creación de un cubo.

    curl -s -i "https://swiftobjectstorage.${region}.oraclecloud.com/v1/${tenancy_namespace}/${bucket_name}" -X PUT -H "X-Auth-Token: ${X_Auth_Token}"
    
  5. Cargue un archivo en el cubo.

    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. Muestre el contenido del cubo.

    curl -s -D /dev/stderr "https://swiftobjectstorage.${region}.oraclecloud.com/v1/${tenancy_namespace}/${bucket_name}" -H "X-Auth-Token: ${X_Auth_Token}" | jq
    
  7. Recupere un archivo del cubo.

    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. Suprima el archivo del cubo.

    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. Suprima el cubo.

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

Enfoque 3: Autenticación basada en token mediante la autenticación v2

Para ilustrar el procedimiento de autorización v2 de la API de Swift de OCI, utilizaremos el paquete Python oficial de la API de Swift OpenStack python-swiftclient 4.5.0 y las dependencias necesarias para la autenticación v2 python-keystoneclient 5.4.0.

Ejemplo:

  1. Ejecute el siguiente comando para asegurarse de que tiene acceso a una versión de Python superior a 3.6. Para obtener más información, consulte Descarga de Python.

    python3 --version
    
  2. Instale los módulos de Python necesarios.

    python3 -m pip install python-swiftclient python-keystoneclient click
    
  3. Puede utilizar el siguiente código para interactuar con la API de Swift de OCI v2. Asegúrese de sustituir los marcadores de posición para <user>, <password>, <region> y <tenancy-namespace> en el siguiente código antes de ejecutarlo.

    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()
    

Agradecimientos

Más recursos de aprendizaje

Explore otros laboratorios en docs.oracle.com/learn o acceda a más contenido de aprendizaje gratuito en el canal YouTube de Oracle Learning. Además, visite education.oracle.com/learning-explorer para convertirse en Oracle Learning Explorer.

Para obtener documentación sobre el producto, visite Oracle Help Center.