Managing snapshots of Azure blobs with PowerShell

In the previous article in this series, we talked about accessing and modifying the properties and metadata of a blob using PowerShell. In this module, we’ll look at how to manage snapshots – adding them, removing them, and viewing them.

Using snapshots lets you keep history for a blob, allowing you to revert to a previous version. In this blog entry, we’ll upload a blob, set the metadata, then take a snapshot. Then we’ll do that a couple more times. Then we’ll examine the snapshot, see how to promote it, and how to delete it.

If you don’t know anything about snapshots, or you need a refresher course, please read about snapshots in the Just Azure series about blob storage, where I explain everything you ever wanted to know about blob snapshots. That article shows how to do snapshots with C# code. We’re going to use PowerShell instead.

Setup

As we’ve seen before, first you need a storage account context. This is the same as in the previous posts. To define a storage account context, you need the storage account name and key. Set the variables to storage account name and key. You can get these from the Storage Account in the Azure Portal.

$StorageAccountName = "yourStorageAccountName"
$StorageAccountKey = "yourStorageAccountKey"

Now let’s set up the storage account context.

$ctx = New-AzureStorageContext -StorageAccountName $StorageAccountName `
         -StorageAccountKey $StorageAccountKey

Upload a file and get a reference to the blob

First, let’s set a container name. You can use an existing container if you like; just plug in the container name. I’m going to create a new container called “snapshots”, and set the access level to “Blob”, which means the container will provide public access to the blobs.

$ContainerName = “snapshots"

New-AzureStorageContainer -Name $ContainerName -Context $ctx -Permission Blob

Now I’m going to upload files from a local directory. I selected pictures, but you can select any kind of files that you want to. Set a variable to the local folder. This way, you don’t have to type it in repetitively. I’ve set this one to match the folder where I have pictures I want to upload.

$localFileDirectory = "D:\_Temp\TestImages\"

Now I’ll set the blob name. I’ll upload each picture to the same blob, so this won’t change.

$BlobName = "RandomPicture.jpg"

Now let’s set the name of the local file and upload the picture.

$localFileName = "DogInCatTree.png"

$localFile = $localFileDirectory + $localFileName

Set-AzureStorageBlobContent -File $localFile -Container $ContainerName `

     -Blob $BlobName -Context $ctx

Now we’ll get a reference to the blob. This will point to the base blob, so we only have to do this the first time, because we’re going to keep uploading pictures to the same blob.

$Blob = Get-AzureStorageBlob -Context $ctx -Container $ContainerName -Blob $BlobName

$CloudBlockBlob = [Microsoft.WindowsAzure.Storage.Blob.CloudBlockBlob] $Blob.ICloudBlob

Now that we have a reference to the blob, we can modify the metadata and create some snapshots.

Create Snapshots

Let’s set the metadata on the blob with one key-value pair. The key will be “filename” and the value will be the file name of the blob that was uploaded. This way, we can tell what the original file was that was uploaded. Then we’ll save the change (SetMetadata) and create a snapshot.

$CloudBlockBlob.Metadata["filename"] = $localFileName

$CloudBlockBlob.SetMetadata()

$CloudBlockBlob.CreateSnapshot()

Let’s upload another picture, set the metadata, and create another snapshot.

$localFileName = "GuyEyeingOreos.png"

$localFile = $localFileDirectory + $localFileName

Upload the file, using the –Force argument that tells it to overwrite the file without prompting if it already exists. If you don’t use this, it will ask if it’s okay to replace the file.

Set-AzureStorageBlobContent -File $localFile -Container $ContainerName -Blob $BlobName -Context $ctx -Force

Set the metadata to hold the name of the original file before taking the snapshot, then take the snapshot.

$CloudBlockBlob.Metadata["filename"] = $localFileName

$CloudBlockBlob.SetMetadata()

$CloudBlockBlob.CreateSnapshot()

Let’s do the whole sequence one more time so we have more snapshots to look at.

$localFileName = "gizmodo_groundhog_texting.jpg"

$localFile = $localFileDirectory + $localFileName

Set-AzureStorageBlobContent -File $localFile -Container $ContainerName `
    -Blob $BlobName -Context $ctx -Force

$CloudBlockBlob.Metadata["filename"] = $localFileName

$CloudBlockBlob.SetMetadata()

$CloudBlockBlob.CreateSnapshot()

Now we have one base blob and 3 snapshots. The snapshots will have metadata that represents the file name used for that blob.

Examine the snapshots

Let’s get a reference to the container, and then list the files in the container and their snapshots, and show just the name and snapshot time.

$Container = Get-AzureStorageContainer -Name $ContainerName -Context $ctx

$Container.CloudBlobContainer.ListBlobs($BlobName, $true, "Snapshots") `

     | select Name, SnapshotTime

image-01

The entry without the snapshot time is the base blob.

Let’s save the list to a variable, then loop through the list and show the snapshot date/time and the filename from the metadata for each entry. I’m not going to show blob name, because they’re all the same.

$ListOfBlobs = $Container.CloudBlobContainer.ListBlobs($BlobName, $true, "Snapshots")

foreach ($CloudBlockBlob in $ListOfBlobs) {

    $CloudBlockBlob.FetchAttributes()

    write-host " snapshot time = " $cloudblockblob.SnapshotTime `

        " filename = " $CloudBlockBLob.Metadata["filename"]

    }

image-02

Notice the base blob has the same metadata as the last snapshot. This makes sense, as we uploaded 3 files, set the metadata, and took snapshots after each one. The last snapshot should match the base blob, and it does.

You can copy a snapshot to a regular blob. Let’s loop through the snapshots and use the filename in the metadata as the new blob name.

foreach ($CloudBlockBlob in $ListOfBlobs) {

    if ($CloudBlockBlob.IsSnapshot)

    {

        $CloudBlockBlob.FetchAttributes()

        $newBlobName = $CloudBlockBlob.Metadata["filename"]

        Start-AzureStorageBlobCopy -ICloudBlob $CloudBlockBlob `

            -DestContainer $ContainerName -DestBlob $newBlobName -Context $ctx

    }

}

Now let’s look at the list of blobs and snapshots in the container.

Get-AzureStorageBlob -Container $ContainerName -Context $ctx `

|     select Name, SnapshotTime

image

Each snapshot was copied back to its original name; you can see they now appear in the container with the original base blob and its snapshots.

Promote a snapshot

Let’s pick a specific snapshot and promote it. This will make that picture the base blob. First, save the list of snapshots for the base blob. Then set the file name you want to look for.

$ListOfBLobs = $Container.CloudBlobContainer.ListBlobs($BlobName, $true, "Snapshots")

$fileNameTarget = "GuyEyeingOreos.png"

1. Now let’s loop through the snapshots until we find one with a matching file name. We’ll save that specific instance in the variable $CloudBlockBlobSnapshot

foreach ($CloudBlockBlob in $ListOfBLobs)

{

    $CloudBlockBlob.FetchAttributes()

    write-host "filename = " $CloudBlockBlob.Metadata["filename"]

    if ($CloudBlockBlob.Metadata["filename"] -eq $fileNameTarget)

    {

        write-host "match found"

        $CloudBlockBlobSnapshot = $CloudBlockBlob

    }

}

Now the $CloudBlockBlobSnapshot points to that one snapshot. To promote the snapshot, go get a reference to the base blob, and then copy the snapshot over the base blob.

$OriginalBlob = Get-AzureStorageBlob -Context $ctx `

    -Container $ContainerName -Blob $BlobName

Start-AzureStorageBlobCopy -ICloudBlob $CloudBlockBlobSnapshot `

     -DestICloudBlob $originalBLob.ICloudBlob -Context $ctx

Get the URL of the original blob and paste it into the browser. You’ll see the base blob now matches the snapshot you selected.

Print out the URI so you can copy it and paste it into the browser.

$originalblob.ICloudBlob.Uri.AbsoluteUri

image-04

Delete a specific snapshot

Let’s delete the snapshot. First I’ll show $CloudBlockBlobSnapshot.SnapshotTime to get the date/time stamp so we can verify that’s the one removed. Then I’ll delete the snapshot we are referencing and get a list of blobs and snapshots for that one base blob.

$CloudBlockBlobSnapshot.SnapshotTime

$CloudBlockBlobSnapshot.Delete()

$Container.CloudBlobContainer.ListBlobs($BlobName, $true, "Snapshots")

image-05

Now we can see there are only two snapshots, and the one we deleted is gone.

Summary

In this article, you’ve seen how to create and view snapshots for a blob. This allows you to retain the history of changes, and retrieve a prior value if needed. You’ve also learned how to promote a snapshot to a regular blo, and how to delete a snapshot. In the next article, I’ll show you how to manage blob leases using PowerShell.

Tags: , ,

2 Responses to “Managing snapshots of Azure blobs with PowerShell”

  1. Daniel Says:

    This line:
    $CloudBlockBlob = [Microsoft.WindowsAzure.Storage.Blob.CloudBlockBlob] $Blob.ICloudBlob
    Generates the following error:

    Cannot convert the “Microsoft.WindowsAzure.Storage.Blob.CloudPageBlob” value of type “Microsoft.WindowsAzure.Storage.Blob.CloudPageBlob” to type
    “Microsoft.WindowsAzure.Storage.Blob.CloudBlockBlob”.
    At line:12 char:1
    + $CloudBlockBlob = [Microsoft.WindowsAzure.Storage.Blob.CloudBlockBlob …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidArgument: (:) [], RuntimeException
    + FullyQualifiedErrorId : ConvertToFinalInvalidCastException

    Any idea?

    • robindotnet Says:

      You are pointing to a page blob, not a block blob. If you want to use a page blob, you need to change the type to CloudPageBlob when doing the conversion.
      Robin

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s


%d bloggers like this: