附註:

搭配 OpenStack Swift API 使用 Oracle Cloud Infrastructure Object Storage Service

簡介

Oracle Cloud Infrastructure (OCI) Object Storage 是一種資料儲存架構,可作為物件管理及組織數位資訊,每個物件都包含資料、描述資料及唯一 ID。與傳統檔案或區塊儲存不同,OCI Object Storage 不依賴階層式結構,因此能夠有效率且可擴展地處理大量非結構化資料。物件儲存在平面位址空間中,可簡化資料擷取,並實現無縫擴展性。此解決方案適用於多媒體內容和備份等各種資料類型,因其彈性、持久性及易於存取,使它成為雲端環境、封存儲存及分散式系統的強大選擇。使用者可透過 HTTP 協定使用 REST 介面與物件儲存服務互動。

OCI 物件儲存服務是雲端儲存解決方案,Oracle 可處理管理複雜性,確保可靠且符合成本效益的資料持久性。此平台的靈活性可讓您以無縫接軌的方式進行擴展,完全不影響效能或服務可靠性。

OCI 物件儲存透過 Amazon S3 相容 API 與 OpenStack Swift API 和 Amazon Simple Storage Service (Amazon S3) 相容。這可讓客戶繼續使用現有的工具 (例如 SDK 從屬端),將對其應用程式進行變更的需求降到最低。如需詳細資訊,請參閱 Amazon S3 Compatibility API 。本教學課程將著重於 OCI OpenStack Swift 相容的 API 使用量。

開始討論 OpenStack Swift API 之前,我們需要釐清 OCI 物件儲存中使用的部分建構。

OpenStack Swift 定義三個建構:「帳戶」、「容器」和「物件」。

我們現在可以識別 OCI 物件儲存與 OpenStack Swift API 之間的等效資源。

目標

必要條件

使用 OCI Swift API

OCI Swift API 區域端點使用一致的 URL 格式 https://swiftobjectstorage.<region-identifier>.oraclecloud.com。例如,美國東部區域 (US-ashburn-1) 中的原生 OCI Swift API 端點為 https://swiftobjectstorage.US-ashburn-1.oraclecloud.com

考慮到區域層次的租用戶層次隔離,OCI Swift API 端點會變成:https://swiftobjectstorage.<region-identifier>.oraclecloud.com/<tenancy-namespace>,其中 <tenancy-namespace> 是要在其中建立儲存區域之租用戶的自動產生物件儲存命名空間字串。如需詳細資訊,請參閱租用戶資訊頁面

OCI Swift API 缺乏區間的概念。依照預設,使用 OCI Amazon S3 相容 API 或 OCI Swift API 建立的儲存設定,會建立在 Oracle Cloud Infrastructure 租用戶的隔間中。您可以為 OCI Amazon S3 相容 API 或 OCI Swift API 指定其他區間,以建立儲存桶。如需詳細資訊,請參閱編輯租用戶的 Amazon S3 相容性 API 和 Swift API 區間指定項目

OCI Swift API 支援三種驗證要求的方法。

方法 1:使用基本認證標頭

使用者名稱的格式為 <username>。例如 john.doe@acme.com。如果您的租用戶與 Oracle Identity Cloud Service 同盟,請使用 oracleidentitycloudservice/<username> 格式。

密碼是針對使用者產生的認證權杖。例如,my-auth-token。如需詳細資訊,請參閱取得認證權杖

每個對 OCI Swift API 的要求都應包含下列標頭。

例如,如果使用者名稱是 oracleidentitycloudservice/john.doe@acme.com,而密碼是 my-auth-token,則標頭看起來會像:

我們將使用官方文件中描述的部分 API 呼叫,請參閱 OpenStack Swift API

範例:

  1. 起始下列必要的環境變數

    user='<username>'
    password='<password>'
    region='<oci-region>'
    tenancy_namespace='<tenancy-namespace>'
    bucket_name='tutorial-bucket'
    object_name='sample.txt'
    
  2. 列出帳戶中的儲存桶,只會列出來自所選 OCI Swift API 區間的儲存桶。

    curl -sS -D /dev/stderr "https://swiftobjectstorage.${region}.oraclecloud.com/v1/${tenancy_namespace}" -u "${user}:${password}" | jq
    
  3. 建立儲存桶。

    curl -sS -i "https://swiftobjectstorage.${region}.oraclecloud.com/v1/${tenancy_namespace}/${bucket_name}" -X PUT -u "${user}:${password}"
    
  4. 將檔案上傳至儲存桶。

    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. 列出儲存桶內容。

    curl -sS -D /dev/stderr "https://swiftobjectstorage.${region}.oraclecloud.com/v1/${tenancy_namespace}/${bucket_name}" -u "${user}:${password}" | jq
    
  6. 從儲存桶擷取檔案。

    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. 刪除儲存桶中的檔案。

    curl -sS -i "https://swiftobjectstorage.${region}.oraclecloud.com/v1/${tenancy_namespace}/${bucket_name}/${object_name}" -X DELETE -u "${user}:${password}"
    
  8. 刪除儲存桶。

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

方法 2:使用 v1 認證的權杖型驗證

您必須呼叫該區域的 OCI Swift API 授權端點,並在要求中包含 X-Storage-UserX-Storage-Pass 標頭。如果認證要求成功,您將會收到含有可用於要求授權之 X-Storage-Token 標頭的回應,以及帳戶之 OCI Swift API 端點的 X-Storage-Url 標頭。

X-Storage-User 標頭的格式為 <tenancy-namespace>:<username>

例如,如果 tenancy-namespaceaxaxnpcrorw5,且使用者名稱與「方法 1」相同,則標頭的值為 axaxnpcrorw5:oracleidentitycloudservice/john.doe@acme.com

X-Storage-Pass 是產生的認證權杖。

範例:

  1. 起始下列必要的環境變數

    user='<username>'
    password='<password>'
    region='<oci-region>'
    tenancy_namespace='<tenancy-namespace>'
    bucket_name='tutorial-bucket'
    object_name='sample.txt'
    
  2. 產生權杖。

    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. 列出帳戶中的儲存桶,只會列出來自所選 OCI Swift API 區間的儲存桶。

    curl -s -D /dev/stderr "https://swiftobjectstorage.${region}.oraclecloud.com/v1/${tenancy_namespace}" -H "X-Auth-Token: ${X_Auth_Token}" | jq
    
  4. 建立儲存桶。

    curl -s -i "https://swiftobjectstorage.${region}.oraclecloud.com/v1/${tenancy_namespace}/${bucket_name}" -X PUT -H "X-Auth-Token: ${X_Auth_Token}"
    
  5. 將檔案上傳至儲存桶。

    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. 列出儲存桶內容。

    curl -s -D /dev/stderr "https://swiftobjectstorage.${region}.oraclecloud.com/v1/${tenancy_namespace}/${bucket_name}" -H "X-Auth-Token: ${X_Auth_Token}" | jq
    
  7. 從儲存桶擷取檔案。

    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. 刪除儲存桶中的檔案。

    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. 刪除儲存桶。

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

方法 3:使用 v2 認證的權杖型驗證

為了說明 OCI Swift API v2 授權程序,我們將使用官方 OpenStack Swift API Python 套裝軟體 python-swiftclient 4.5.0 ,以及 v2 認證 python-keystoneclient 5.4.0 所需的相依性。

範例:

  1. 請執行下列命令,以確保您能夠存取 3.6 以上的 Python 版本。如需詳細資訊,請參閱下載 Python

    python3 --version
    
  2. 安裝所需的 Python 模組。

    python3 -m pip install python-swiftclient python-keystoneclient click
    
  3. 您可以使用下列程式碼與 OCI Swift API v2 互動。執行之前,請務必在下列程式碼中取代 <user><password><region><tenancy-namespace> 的預留位置。

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

認可

其他學習資源

瀏覽 docs.oracle.com/learn 的其他實驗室,或前往 Oracle Learning YouTube 頻道存取更多免費學習內容。此外,請造訪 education.oracle.com/learning-explorer 以成為 Oracle Learning Explorer。

如需產品文件,請造訪 Oracle Help Center