Observação:

Usar o Oracle Cloud Infrastructure Object Storage Service com a API Swift OpenStack

Introdução

O Oracle Cloud Infrastructure (OCI) Object Storage é uma arquitetura de armazenamento de dados que gerencia e organiza informações digitais como objetos, cada um compreendendo dados, metadados e um identificador exclusivo. Ao contrário do armazenamento tradicional de arquivos ou blocos, o OCI Object Storage não depende de uma estrutura hierárquica, permitindo um manuseio eficiente e escalável de grandes quantidades de dados não estruturados. Os objetos são armazenados em um espaço de endereço simples, simplificando a recuperação de dados e permitindo uma escalabilidade perfeita. Esta solução é ideal para diversos tipos de dados, como conteúdo multimídia e backups, tornando-a uma escolha robusta para ambientes de nuvem, armazenamento de arquivamento e sistemas distribuídos devido à sua flexibilidade, durabilidade e facilidade de acesso. Os usuários interagem com o serviço de armazenamento de objetos usando uma interface REST sobre o protocolo HTTP.

O serviço OCI Object Storage é uma solução de armazenamento baseada em nuvem na qual a Oracle lida com a complexidade de gerenciamento, garantindo durabilidade de dados confiável e econômica. A elasticidade da plataforma permite um início gradual com a capacidade de dimensionar sem problemas, tudo sem comprometer o desempenho ou a confiabilidade do serviço.

O OCI Object Storage fornece compatibilidade de API com a API OpenStack Swift e o Amazon Simple Storage Service (Amazon S3) por meio da API de Compatibilidade com Amazon S3. Isso permite que os clientes continuem usando suas ferramentas existentes (por exemplo, clientes SDK), minimizando a necessidade de fazer alterações em seus aplicativos. Para obter mais informações, consulte API de Compatibilidade com Amazon S3. Este tutorial se concentrará no consumo de API compatível com o OCI OpenStack Swift.

Antes de começarmos a discutir sobre a API Swift OpenStack, precisamos esclarecer algumas das construções usadas no OCI Object Storage.

O Swift OpenStack define três construções: Conta, Contêiner e Objeto.

Agora podemos identificar recursos equivalentes entre o OCI Object Storage e a API Swift OpenStack.

Objetivos

Pré-requisitos

Usar API Swift do OCI

Os pontos finais regionais da API OCI Swift usam um formato de URL consistente de https://swiftobjectstorage.<region-identifier>.oraclecloud.com. Por exemplo, o ponto final nativo da API OCI Swift na região Leste dos EUA (US-ashburn-1) é https://swiftobjectstorage.US-ashburn-1.oraclecloud.com.

Considerando o isolamento no nível do tenant no nível da região, o ponto final da API Swift do OCI se torna: https://swiftobjectstorage.<region-identifier>.oraclecloud.com/<tenancy-namespace>, em que <tenancy-namespace> é a string de namespace do serviço Object Storage gerada automaticamente da tenancy na qual criar repositórios. Para obter mais informações, consulte a página Informações da Tenancy.

A API Swift da OCI não tem o conceito de compartimento. Por padrão, os buckets criados usando a API de Compatibilidade com Amazon S3 do OCI ou a API Swift do OCI são criados no compartimento root da tenancy do Oracle Cloud Infrastructure. Você pode designar outro compartimento para a API de Compatibilidade com Amazon S3 do OCI ou a API Swift do OCI para criar buckets. Para obter mais informações, consulte Editando Designações de Compartimento da API de Compatibilidade com o Amazon S3 e da API Swift da Tenancy.

A API OCI Swift suporta três abordagens para autenticar solicitações.

Abordagem 1: Usar Cabeçalho de Autorização Básica

O nome do usuário tem o formato <username>. Por exemplo, john.doe@acme.com. Se sua tenancy for federada com o Oracle Identity Cloud Service, use o formato oracleidentitycloudservice/<username>.

A senha é o token de autenticação gerado para o usuário. Por exemplo, my-auth-token. Para obter mais informações, consulte Como Obter um Token de Autenticação.

Cada solicitação para a API Swift do OCI deve incluir o cabeçalho a seguir.

Por exemplo, se o nome de usuário for oracleidentitycloudservice/john.doe@acme.com e a senha for my-auth-token, o cabeçalho terá a seguinte aparência:

Usaremos algumas das chamadas de API descritas na documentação oficial. Consulte OpenStack Swift API.

Exemplo:

  1. Inicialize as variáveis de ambiente necessárias a seguir.

    user='<username>'
    password='<password>'
    region='<oci-region>'
    tenancy_namespace='<tenancy-namespace>'
    bucket_name='tutorial-bucket'
    object_name='sample.txt'
    
  2. Liste buckets na conta; somente buckets dos compartimentos selecionados da API Swift do OCI serão listados.

    curl -sS -D /dev/stderr "https://swiftobjectstorage.${region}.oraclecloud.com/v1/${tenancy_namespace}" -u "${user}:${password}" | jq
    
  3. Criar um bucket.

    curl -sS -i "https://swiftobjectstorage.${region}.oraclecloud.com/v1/${tenancy_namespace}/${bucket_name}" -X PUT -u "${user}:${password}"
    
  4. Faça upload de um arquivo para o 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. Liste o conteúdo do bucket.

    curl -sS -D /dev/stderr "https://swiftobjectstorage.${region}.oraclecloud.com/v1/${tenancy_namespace}/${bucket_name}" -u "${user}:${password}" | jq
    
  6. Extraia um arquivo do 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. Exclua o arquivo do bucket.

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

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

Abordagem 2: Autenticação Baseada em Token usando a Autenticação v1

Você precisará chamar o ponto final de autorização da API Swift do OCI para a região e incluir os cabeçalhos X-Storage-User e X-Storage-Pass na solicitação. Se a solicitação de autenticação for bem-sucedida, você receberá uma resposta com o cabeçalho X-Storage-Token que pode ser usado para autorização de solicitação e o cabeçalho X-Storage-Url com o ponto final da API Swift do OCI para a conta.

O cabeçalho X-Storage-User tem o formato <tenancy-namespace>:<username>.

Por exemplo, se tenancy-namespace for axaxnpcrorw5 e o nome de usuário for o mesmo da Abordagem 1, o valor do cabeçalho será axaxnpcrorw5:oracleidentitycloudservice/john.doe@acme.com.

O X-Storage-Pass é o token de autenticação gerado.

Exemplo:

  1. Inicialize as variáveis de ambiente necessárias a seguir.

    user='<username>'
    password='<password>'
    region='<oci-region>'
    tenancy_namespace='<tenancy-namespace>'
    bucket_name='tutorial-bucket'
    object_name='sample.txt'
    
  2. Gerar um 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. Liste buckets na conta; somente buckets dos compartimentos selecionados da API Swift do OCI serão listados.

    curl -s -D /dev/stderr "https://swiftobjectstorage.${region}.oraclecloud.com/v1/${tenancy_namespace}" -H "X-Auth-Token: ${X_Auth_Token}" | jq
    
  4. Criar um bucket.

    curl -s -i "https://swiftobjectstorage.${region}.oraclecloud.com/v1/${tenancy_namespace}/${bucket_name}" -X PUT -H "X-Auth-Token: ${X_Auth_Token}"
    
  5. Faça upload de um arquivo para o 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. Liste o conteúdo do 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. Extraia um arquivo do 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. Exclua o arquivo do 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. Exclua o bucket.

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

Abordagem 3: Autenticação Baseada em Token usando a Autenticação v2

Para ilustrar o procedimento de autorização v2 da API OCI Swift, usaremos o pacote oficial OpenStack Swift API Python python-swiftclient 4.5.0 e as dependências necessárias para a autenticação v2 python-keystoneclient 5.4.0.

Exemplo:

  1. Execute o comando a seguir para garantir que você tenha acesso a uma versão do Python acima de 3.6. Para obter mais informações, consulte Download do Python.

    python3 --version
    
  2. Instale os módulos Python obrigatórios.

    python3 -m pip install python-swiftclient python-keystoneclient click
    
  3. Você pode usar o código a seguir para interagir com a API Swift da OCI v2. Certifique-se de substituir os placeholders para <user>, <password>, <region> e <tenancy-namespace> no código a seguir antes de executar.

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

Confirmações

Mais Recursos de Aprendizagem

Explore outros laboratórios em docs.oracle.com/learn ou acesse mais conteúdo de aprendizado gratuito no canal Oracle Learning YouTube. Além disso, visite education.oracle.com/learning-explorer para se tornar um Oracle Learning Explorer.

Para obter a documentação do produto, visite o Oracle Help Center.