I am trying to copy all containers inside of a storage account into a single container on another storage account. I've gotten this working on my own machine without any issues but I would like to automate it using Azure Automation.
When running a standard powershell script, all of the async calls are happening synchronously. To resolve this, I tried adding a "Powershell Workflow" runbook. The probelm with that is that I have a few calls to Azure storage commands which require an instance of an AzureStorageContext
. The problem is that I cannot bind the context to anything because it will have been serialized into a string.
I have the following code:
$destinationContext = (New-AzureStorageContext -StorageAccountName $destinationAccountName -StorageAccountKey $destinationAccountKey)
$sourceContext = (New-AzureStorageContext -StorageAccountName $prodAccountName -StorageAccountKey $prodAccountKey)
$allContainers = Get-AzureStorageContainer -Context $sourceContext
$startTime = Get-Date -Format "yyyyMMddhhmmss"
foreach ($container in $allContainers.Name)
{
$allBlobs = (Get-AzureStorageBlob -Container $container -Context $sourceContext).Name
foreach -Parallel ($blob in $allBlobs)
{
$fileName = $startTime + "/" + $container + "/" + $blob
Write-Information "Copying $fileName"
Start-AzureStorageBlobCopy -SrcBlob $blob -DestBlob $fileName -SrcContainer $container -Context $sourceContext -DestContext $destinationContext -DestContainer $destinationContainer
}
}
A standard workaround for this is to use an InlineScript
block to process anything that requires the context object. However, if I were to do that, I would lose the ability to copy blobs in parallel.
Is there any way to do this on Azure Automation while still starting the copy command for all blobs in parallel?
You should be able to put the InlineScript block within the foreach -parallel, that will run all the InlineScripts in parallel:
$destinationContext = (New-AzureStorageContext -StorageAccountName $destinationAccountName -StorageAccountKey $destinationAccountKey)
$sourceContext = (New-AzureStorageContext -StorageAccountName $prodAccountName -StorageAccountKey $prodAccountKey)
$allContainers = Get-AzureStorageContainer -Context $sourceContext
$startTime = Get-Date -Format "yyyyMMddhhmmss"
foreach ($container in $allContainers.Name)
{
$allBlobs = (Get-AzureStorageBlob -Container $container -Context $sourceContext).Name
foreach -Parallel ($blob in $allBlobs)
{
InlineScript {
$destinationContext = (New-AzureStorageContext -StorageAccountName $using:destinationAccountName -StorageAccountKey $using:destinationAccountKey)
$sourceContext = (New-AzureStorageContext -StorageAccountName $using:prodAccountName -StorageAccountKey $using:prodAccountKey)
$fileName = $using:startTime + "/" + $using:container + "/" + $using:blob
Write-Information "Copying $fileName"
Start-AzureStorageBlobCopy -SrcBlob $using:blob -DestBlob $fileName -SrcContainer $using:container -Context $sourceContext -DestContext $destinationContext -DestContainer $using:destinationContainer
}
}
}
Alternatively, you could have a "master" runbook that starts a bunch of runbook jobs for a "single blob transfer" runbook, where each job takes in a different blob to transfer. All of these runbook jobs would run in parallel on the Azure Automation service.