Python sdk копирует большой двоичный объект из контейнера в контейнер

#python-3.x #azure #azure-blob-storage #azure-python-sdk

Вопрос:

Я надеюсь, что кто-нибудь может помочь с этой проблемой, которая меня немного смущает.

Я пытаюсь создать сценарий резервного копирования для контейнера хранения. Чего я пытаюсь добиться, так это скопировать содержимое контейнера из контейнера A в контейнер B.

Просто чтобы прояснить мой сценарий, это структура моих хранилищ.

Хранение A:

 storageaccountout 
 |--- Containers
   |---- new blob
     |---newfile.txt
 

В учетной записи хранения A у меня есть контейнер с именем newblob , и в этом большом двоичном объекте у меня только один файл.

С другой стороны, если бы у меня было хранилище B

Хранилище B:

 Storageaccountin
  |--- Containers
    
 

В хранилище B ничего нет, только большой двоичный объект по умолчанию $logs

То, что я пытаюсь сделать, — это скопировать большой двоичный объект контейнера A в большой двоичный объект контейнера B.

У меня есть этот сценарий:

 from azure.storage.blob import BlobClient, BlobServiceClient
from azure.storage.blob import ResourceTypes, AccountSasPermissions
from azure.storage.blob import generate_account_sas    
from datetime import *


# Source Client
connection_string = 'connection.string' # The connection string for the source container
account_key = 'key' # The account key for the source container
source_container_name = 'newblob' # Name of container which has blob to be copied
blob_name = 'lastfile.txt' # Name of the blob you want to copy
destination_container_name = 'incontainer' # Name of container where blob will be copied


# Target Client
target_connection_string = 'connection-string'
target_account_key = 'key'
source_container_name = source_container_name
target_blob_name = 'newfile.txt'
target_destination_blob = 'newblob'
# Create client
client = BlobServiceClient.from_connection_string(connection_string) 

# Create target client
target_client = BlobServiceClient.from_connection_string(target_connection_string)

# Create sas token for blob
sas_token = generate_account_sas(
    account_name = client.account_name,
    account_key = account_key, 
    resource_types = ResourceTypes(object=True, container=True),
    permission= AccountSasPermissions(read=True,list=True),
    # start = datetime.now(),
    expiry = datetime.utcnow()   timedelta(hours=4) # Token valid for 4 hours
)

# Create blob client for source blob
source_blob = BlobClient(
    client.url,
    container_name = source_container_name, 
    blob_name = blob_name,
    credential = sas_token
)


# target client

target_sas_token = generate_account_sas(
    account_name = target_client.account_name,
    account_key = target_account_key, 
    resource_types = ResourceTypes(object=True, container=True),
    permission= AccountSasPermissions(read=True,list=True),
    # start = datetime.now(),
    expiry = datetime.utcnow()   timedelta(hours=4) # Token valid for 4 hours
)

# Create blob client for source blob
source_blob = BlobClient(
    target_client.url,
    container_name = source_container_name, 
    blob_name = target_blob_name,
    credential = target_sas_token
)

# Create new blob and start copy operation.
# new_blob = client.get_blob_client(destination_container_name, blob_name)    
new_blob = client.get_blob_client(target_destination_blob, target_blob_name)    
new_blob.start_copy_from_url(source_blob.url)
 

Теперь, когда я запускаю этот скрипт, я получаю следующую ошибку:

 Traceback (most recent call last):
  File "/Users/user/miniforge3/lib/python3.9/site-packages/azure/storage/blob/_blob_client.py", line 1922, in start_copy_from_url
    return self._client.blob.start_copy_from_url(**options)
  File "/Users/user/miniforge3/lib/python3.9/site-packages/azure/storage/blob/_generated/operations/_blob_operations.py", line 2280, in start_copy_from_url
    raise HttpResponseError(response=response, model=error)
azure.core.exceptions.HttpResponseError: Operation returned an invalid status 'Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/user/Desktop/AzCopy/blob.py", line 35, in <module>
    new_blob.start_copy_from_url(source_blob.url)
  File "/Users/user/miniforge3/lib/python3.9/site-packages/azure/core/tracing/decorator.py", line 83, in wrapper_use_tracer
    return func(*args, **kwargs)
  File "/Users/user/miniforge3/lib/python3.9/site-packages/azure/storage/blob/_blob_client.py", line 1924, in start_copy_from_url
    process_storage_error(error)
  File "/Users/user/miniforge3/lib/python3.9/site-packages/azure/storage/blob/_shared/response_handlers.py", line 150, in process_storage_error
    error.raise_with_traceback()
  File "/Users/user/miniforge3/lib/python3.9/site-packages/azure/core/exceptions.py", line 247, in raise_with_traceback
    raise super(AzureError, self).with_traceback(self.exc_traceback)
  File "/Users/user/miniforge3/lib/python3.9/site-packages/azure/storage/blob/_blob_client.py", line 1922, in start_copy_from_url
    return self._client.blob.start_copy_from_url(**options)
  File "/Users/user/miniforge3/lib/python3.9/site-packages/azure/storage/blob/_generated/operations/_blob_operations.py", line 2280, in start_copy_from_url
    raise HttpResponseError(response=response, model=error)
azure.core.exceptions.ResourceNotFoundError: Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.
RequestId:199c7c8a-501e-00a3-7418-aed966000000
Time:2021-09-20T12:08:20.0231825Z
ErrorCode:CannotVerifyCopySource
Error:None
 

Насколько я понимаю, это ошибка с подписью общего доступа, но как это работает, если я даю строку подключения и ключ хранилища, почему я получаю эту ошибку.

Большое вам спасибо за любую помощь, которую вы можете мне оказать, и, пожалуйста, если вам нужна дополнительная информация, не стесняйтесь спрашивать

Комментарии:

1. Пожалуйста, попробуйте удалить следующее из кода генерации токенов sas: start = datetime.now(), .

2. Большое вам спасибо за ваш ответ. Я попытался удалить строку, которую вы посоветовали, но я получаю новую ошибку azure.core.exceptions.ResourceNotFoundError: Operation returned an invalid status 'The specified container does not exist.'

3. Существует ли как исходный, так и целевой контейнер больших двоичных объектов?

4. Ммм, я исправил код, чтобы он работал. Мне не хватало контейнера, в который можно было бы скопировать содержимое. Возможно, вы можете помочь мне решить эту проблему, но я искал что-то о том, как скопировать из контейнера (учетная запись хранилища A) в совершенно другую учетную запись хранилища. Выполнимо ли это? большое вам спасибо за любую помощь. Потому что с фактическим кодом я могу копировать только из контейнера в контейнер в одну учетную запись хранения

5. I was looking to something about how to copy from container (storage account A) into a totally difference storage account. Is this doable? — Это вполне выполнимо. Что вам нужно было бы сделать, так это создать клиент для вашей целевой учетной записи хранения (давайте назовем его target_client так, а затем используйте это вместо client здесь: new_blob = client.get_blob_client(destination_container_name, blob_name) .

Ответ №1:

Большое спасибо @GauravMantri за его терпение и помощь.

Решение для копирования хранилища больших двоичных объектов из одного контейнера в другой выглядит следующим образом:

 from azure.storage.blob import BlobClient, BlobServiceClient
from azure.storage.blob import ResourceTypes, AccountSasPermissions
from azure.storage.blob import generate_account_sas    
from datetime import *




#================================ SOURCE ===============================
# Source Client
connection_string = '' # The connection string for the source container
account_key = '' # The account key for the source container
source_container_name = '' # Name of container which has blob to be copied
blob_name = '' # Name of the blob you want to copy
destination_container_name = '' # Name of container where blob will be copied



# Create client
client = BlobServiceClient.from_connection_string(connection_string) 



# Create sas token for blob
sas_token = generate_account_sas(
    account_name = client.account_name,
    account_key = account_key, 
    resource_types = ResourceTypes(object=True, container=True),
    permission= AccountSasPermissions(read=True,list=True),
    # start = datetime.now(),
    expiry = datetime.utcnow()   timedelta(hours=4) # Token valid for 4 hours
)

# Create blob client for source blob
source_blob = BlobClient(
    client.url,
    container_name = source_container_name, 
    blob_name = blob_name,
    credential = sas_token
)


# ============================= TARGET =======================================

# Target Client
target_connection_string = ''
target_account_key = ''
source_container_name = source_container_name
target_blob_name = ''
target_destination_blob = ''

# Create target client
target_client = BlobServiceClient.from_connection_string(target_connection_string)


# Create new blob and start copy operation.
# new_blob = client.get_blob_client(destination_container_name, blob_name)    
new_blob = target_client.get_blob_client(target_destination_blob, target_blob_name)    
new_blob.start_copy_from_url(source_blob.url)