Last active
October 9, 2023 10:38
-
-
Save andreasbotsikas/a0500aa976896d070469 to your computer and use it in GitHub Desktop.
Move Azure blobs from one container to another
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using Microsoft.WindowsAzure.Storage; | |
using Microsoft.WindowsAzure.Storage.Blob; | |
/// <summary> | |
/// Moves blobs from one container to another | |
/// Install-Package WindowsAzure.Storage | |
/// </summary> | |
namespace MoveBlobs | |
{ | |
class Program | |
{ | |
// Get the following settings from your azure portal | |
private const string FromAccountConnectionString = "DefaultEndpointsProtocol=https;AccountName=;AccountKey="; | |
private const string ToAccountConnectionString = "DefaultEndpointsProtocol=https;AccountName=;AccountKey="; | |
static void Main(string[] args) | |
{ | |
var fromAccount = CloudStorageAccount.Parse(FromAccountConnectionString); | |
var fromContainer = fromAccount.CreateCloudBlobClient().GetContainerReference("vhds"); | |
var toAccount = CloudStorageAccount.Parse(ToAccountConnectionString); | |
var toContainer = toAccount.CreateCloudBlobClient().GetContainerReference("vhds"); | |
// Copy all blobs from the vhds container | |
CopyBlobs(fromContainer, toContainer); | |
MonitorCopy(toContainer); | |
Console.WriteLine("Finished copying. Press any key to exit."); | |
Console.ReadKey(); | |
} | |
/// <summary> | |
/// Reports the copy status and retries failed copies | |
/// </summary> | |
/// <param name="destContainer">The container that has the placeholders for the incoming blobs</param> | |
public static void MonitorCopy(CloudBlobContainer destContainer) | |
{ | |
bool pendingCopy = true; | |
while (pendingCopy) | |
{ | |
Console.Clear(); | |
Console.WriteLine("Status update {0:dd/MM/yyy HH:mm:ss}", DateTime.Now); | |
pendingCopy = false; | |
var destBlobList = destContainer.ListBlobs("",true, BlobListingDetails.Copy); | |
foreach (var dest in destBlobList) | |
{ | |
var destBlob = dest as CloudBlob; | |
// Skip blob if no copy state | |
if (destBlob.CopyState == null) | |
{ | |
continue; | |
} | |
// If failed or aborted restart | |
if (destBlob.CopyState.Status == CopyStatus.Aborted || | |
destBlob.CopyState.Status == CopyStatus.Failed) | |
{ | |
pendingCopy = true; | |
Console.WriteLine("Restarting copy for {0}", destBlob.Name); | |
destBlob.StartCopy(destBlob.CopyState.Source); | |
} | |
// If it's pending, we will wait | |
else if (destBlob.CopyState.Status == CopyStatus.Pending) | |
{ | |
pendingCopy = true; | |
} | |
Console.WriteLine("{0}:{1}",destBlob.Name, destBlob.CopyState.Status); | |
} | |
// Wait for 100 secs | |
System.Threading.Thread.Sleep(100000); | |
}; | |
} | |
/// <summary> | |
/// Retrieves the security token for one day read access to the blob | |
/// </summary> | |
/// <param name="container">The container that has the blobs</param> | |
/// <returns></returns> | |
public static string GetOneDayReadToken(CloudBlobContainer container) | |
{ | |
//Set the expiry time and permissions for the container. | |
//In this case no start time is specified, so the shared access signature becomes valid immediately. | |
SharedAccessBlobPolicy sasConstraints = new SharedAccessBlobPolicy(); | |
sasConstraints.SharedAccessExpiryTime = DateTime.UtcNow.AddHours(24); | |
// We need Read permission only | |
sasConstraints.Permissions = SharedAccessBlobPermissions.Read; | |
//Generate the shared access signature on the container, setting the constraints directly on the signature. | |
return container.GetSharedAccessSignature(sasConstraints); | |
} | |
/// <summary> | |
/// Schedule copy for all blobs from srcContainer to destContainer | |
/// </summary> | |
/// <param name="srcContainer">From which container</param> | |
/// <param name="destContainer">To which container</param> | |
public static void CopyBlobs(CloudBlobContainer srcContainer,CloudBlobContainer destContainer) | |
{ | |
// get the SAS token to use for all blobs | |
string blobToken = GetOneDayReadToken(srcContainer); | |
var srcBlobList = srcContainer.ListBlobs("", true, BlobListingDetails.None); | |
foreach (var src in srcBlobList) | |
{ | |
var srcBlob = src as CloudBlob; | |
// Create appropriate destination blob type to match the source blob | |
CloudBlob destBlob; | |
if (srcBlob.Properties.BlobType == BlobType.BlockBlob) | |
{ | |
destBlob = destContainer.GetBlockBlobReference(srcBlob.Name); | |
} | |
else | |
{ | |
destBlob = destContainer.GetPageBlobReference(srcBlob.Name); | |
} | |
// copy using src blob as SAS | |
destBlob.StartCopy(new Uri(srcBlob.Uri.AbsoluteUri + blobToken)); | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// <summary> | |
/// Rename a blob | |
/// </summary> | |
/// <param name="container">The container that has the blob</param> | |
/// <param name="oldName">The old name</param> | |
/// <param name="newName">The new name</param> | |
public static void RenamePageBlob(CloudBlobContainer container, string oldName, string newName) | |
{ | |
var source = container.GetBlobReferenceFromServer(oldName); | |
var target = container.GetPageBlobReference(newName); | |
target.StartCopy(source.Uri); | |
while (target.CopyState.Status == CopyStatus.Pending) | |
{ | |
Console.WriteLine("{0:HH:mm:ss} Waiting", DateTime.Now); | |
System.Threading.Thread.Sleep(1000); | |
} | |
if (target.CopyState.Status != CopyStatus.Success) | |
throw new ApplicationException("Rename failed: " + target.CopyState.Status); | |
source.Delete(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment