Skip to content

Instantly share code, notes, and snippets.

@andreasbotsikas
Last active October 9, 2023 10:38
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save andreasbotsikas/a0500aa976896d070469 to your computer and use it in GitHub Desktop.
Save andreasbotsikas/a0500aa976896d070469 to your computer and use it in GitHub Desktop.
Move Azure blobs from one container to another
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));
}
}
}
}
/// <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