Automation–Automating Hybrid Clouds with Windows Azure and PowerShell (Part 4): Public Cloud Environment Deprovisioning PowerShell Examples

Hello once again!

Here we are at the end of this blog series: Part 4 of the Automating Hybrid Clouds with Windows Azure and PowerShell blog series - Public Cloud Environment Deprovisioning PowerShell Examples. I do think you will be surprised to see how easy it is to remove everything you added.

Before we move on to this content, here are the requisite references to the previous three parts of this blog series:

Okay, now for the good part, let’s see what it takes to remove everything you worked so hard to put up there in the first place.


Public Cloud Environment Deprovisioning PowerShell Examples

The following is a list of the high level concept commands that will be covered in this post:

High Level Concept Commands

  1. Remove Windows Azure VM
  2. Remove Windows Azure VM Image
  3. Remove Windows Azure VM Specific Disk (associated to Project)
  4. Remove Windows Azure Storage Account (and Storage Account Resources)
  5. Remove Windows Azure Storage Blob(s)
  6. Remove Windows Azure Storage Container(s)
  7. Remove Windows Azure Cloud Service
  8. Remove Windows Azure Affinity Group
  9. Remove Windows Azure Subscription

Pre-Requisites

We obviously need a few things before we get started:

  1. Windows Server
  2. Windows Azure PowerShell Module
    Direct Download Link: http://go.microsoft.com/?linkid=9811175&clcid=0x409
  3. Something to Deprovision (like the Windows Azure Environment Resources set up in tests of the previous portions of this blog post)
  4. An Established Windows Azure Subscription Connection ( Please Reference Part 2 for details ).
    Note This portion of the script will be included in the overall script at the end of the post, just not covered in full separately here at the top.

Pre-Requisite Setup

Once again, we have to ensure a connection to the Windows Azure Subscription has been established before we proceed.

It is entirely possible this is already Selected/Set on the system where have been executing the Windows Azure PowerShell commands.

If this is the case, simply execute the following command:

001 Get-AzureSubscription

Result Option 1: Data Returned for BOTH Subscription and CurrentStorageAccountName

If the Get-AzureSubscription command results in something like this, you are good to go:

image

Note The CurrentStorageAccountName field is important for these examples. If this is blank, you will have to complete more steps before proceeding (see below).

Result Option 2: No Data Returned

If the Get-AzureSubscription command results in a NULL value, you will have to complete the necessary steps for an Established Windows Azure Subscription Connection.

This region is covered 100% in Part 2 of this blog series.

image

For reference, here is the link:
Automating Hybrid Clouds with Windows Azure and PowerShell (Part 2): Public Cloud Environment Provisioning PowerShell Examples

Result Option 3: Data Returned for Subscription BUT not CurrentStorageAccountName

If the Get-AzureSubscription command results in NULL CurrentStorageAccountName field data, execute the following commands:

001 002 003 004 005 006 007 $AzureSubscriptionName = "Windows Azure MSDN - Visual Studio Ultimate" $ProjectName = "BCBWFDemo" $ProjectNameLower = $ProjectName.ToLower() $AzureStorageAccountName = $ProjectNameLower Set-AzureSubscription -SubscriptionName $AzureSubscriptionName -CurrentStorageAccountName $AzureStorageAccountName Get-AzureSubscription

Note The variables on lines 001 and 002 should be changed to fit your environment/deployment.


Begin Deprovision…

With the Connection to a Windows Azure Subscription Established, Deprovisioning of Windows Azure resources associated with that Subscription and Storage Account can be completed.

Because many of the commands in the Deprovision process are very simple, I have grouped them into sections that can easily be executed together. They can be executed individually if you like, this is just for the example.

Note Within the examples, I have repeated the required variable declarations to successfully execute each of the commands (per section).

Final thing before we get to the commands - here is a screenshot of my…

Windows Azure Environment (all items) BEFORE Deprovision Commands

image

Note I will also show individual breakdown screenshots for each of the Deprovision sections below.

Oh, and because many of the resources have dependencies, be sure to execute them in the recommended order here.


Remove Windows Azure VM and Windows Azure VM Image

Virtual Machines BEFORE

image

Images BEFORE

image

Example PowerShell Script to Remove the Windows Azure VM and Image

001 002 003 004 005 006 007 008 009 $ProjectName = "BCBWFDemo" $ProjectNameLower = $ProjectName.ToLower() $VMName = "{0}-001" -f $ProjectNameLower $ServiceName = $ProjectName $ImageName = $ProjectName #Remove Windows Azure VM and Image Remove-AzureVM -Name $VMName -ServiceName $ServiceName Remove-AzureVMImage -ImageName $ImageName

Note As can be seen, all other variables are derived from the $ProjectName variable. This is consistent with the example Provisioning PowerShell (and Workflow) Examples. Feel free to leverage/update the variables as desired to fit your environment/deployment.

Execution Results

image

Virtual Machines AFTER

image

Images AFTER

image


Remove Windows Azure VM Specific Disk (associated to Project)

Disks BEFORE

image

Note The image above does not show that the “BCBWFDemo…” Disk is attached to a Virtual Machine. This is usually not the case directly after a Virtual Machine is removed. I just happened wait long enough before taking the screenshot and executing the next command. The following commands do take this “wait time” into account with a simple example of a “check for status” loop based on Disk Data.

Example PowerShell Script to Remove the associated Windows Azure VM Disk

001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 $ProjectName = "BCBWFDemo" #Remove Windows Azure VM Specific Disk do { "Disk Attachments being Removed..." (Get-AzureDisk | where {$_.DiskName -match $ProjectName}).AttachedTo Start-Sleep -Seconds 30 } until ((Get-AzureDisk | where {$_.DiskName -match $ProjectName}).AttachedTo.Length -eq 0) Start-Sleep -Seconds 15 if ((Get-AzureDisk | where {$_.DiskName -match $ProjectName}).AttachedTo.Length -eq 0) { $AzureDiskToRemove = Get-AzureDisk | where {$_.DiskName -match $ProjectName} $AzureDiskToRemove.AttachedTo $AzureDiskToRemove | Remove-AzureDisk }

Note Obviously this is a simple example of what you can do to remove the associated Windows Azure VM Disk for the Project VM. There are many ways to program the wait time. This is one of them. You may also just want to wait until the disk is fully detached from other resources by watching it in the portal).

Execution Results

image

Disks AFTER

image


Remove Windows Azure Storage Account Resources

Storage BEFORE

image

Containers BEFORE

image

Blobs BEFORE

image

image

Note Removal of the Windows Azure Storage Account will perform a cascading removal of the Windows Azure Storage Containers and Windows Azure Storage Blob(s). I will break those examples out separately, but if you want to remove everything all at once, simply leverage the following command.

Example PowerShell Script to Remove the Windows Azure Storage Account Resources

001 002 003 004 005 006 $ProjectName = "BCBWFDemo" $ProjectNameLower = $ProjectName.ToLower() $AzureStorageAccountName = $ProjectNameLower #Remove Windows Azure Storage Account Resources Remove-AzureStorageAccount -StorageAccountName $AzureStorageAccountName

Note Depending on your starting point for this example, you may already have defined the $AzureStorageAccountName variable.

Execution Results

image

Storage AFTER

image

Note With the removal of the Windows Azure Storage Account went the associated Windows Azure Storage Containers and Windows Azure Storage Blobs. The following are the individual example commands for each of those if specified removal is desired.


Remove Windows Azure Storage Blob(s)

001 002 003 004 005 006 007 008 009 010 $ProjectName = "BCBWFDemo" $ProjectNameLower = $ProjectName.ToLower() $ProjectCopiedBlobName = "{0}_copy.vhd" -f $ProjectName $ProjectContainerName = $ProjectNameLower $ProjectBlobName = "{0}.vhd" -f $ProjectName $GenericContainerName = "vhds" #Remove Windows Azure Storage Blobs Remove-AzureStorageBlob -Blob $ProjectCopiedBlobName -Container $ProjectContainerName Remove-AzureStorageBlob -Blob $ProjectBlobName -Container $GenericContainerName

Remove Windows Azure Storage Container(s)

001 002 003 004 005 006 007 008 $ProjectName = "BCBWFDemo" $ProjectNameLower = $ProjectName.ToLower() $ProjectContainerName = $ProjectNameLower $GenericContainerName = "vhds" #Remove Windows Azure Storage Containers Remove-AzureStorageContainer -Name $ProjectContainerName -Force Remove-AzureStorageContainer -Name $GenericContainerName -Force

Remove Windows Azure Cloud Service and Windows Azure Affinity Group

Cloud Services BEFORE

image

Affinity Groups BEFORE

image

Example PowerShell Script to Remove the Windows Azure Cloud Service and Affinity Group

001 002 003 004 005 006 007 $ProjectName = "BCBWFDemo" $ServiceName = $ProjectName $AffinityGroupName = $ProjectName #Remove Windows Azure Cloud Service and Affinity Group Remove-AzureService -ServiceName $ServiceName -Force Remove-AzureAffinityGroup -Name $AffinityGroupName

Execution Results

image

Cloud Services AFTER

image

Affinity Groups AFTER

image


…End Deprovision

And just like that, all the project specific Windows Azure Environment resources have been removed.

Windows Azure Environment (all items) BEFORE Deprovision Commands

image


Putting it all together

Okay, once again, here is the portion of the blog post where I put all the above examples together in one copy/paste-able script. You will see, for the sake of simplicity (and line count), I did not add “If Checking” into these examples – feel free to add whatever wrapper logic you want, as desired. Okay, here it is (a destructive 92 lines of PowerShell):

001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 032 033 034 035 036 037 038 039 040 041 042 043 044 045 046 047 048 049 050 051 052 053 054 055 056 057 058 059 060 061 062 063 064 065 066 067 068 069 070 071 072 073 074 075 076 077 078 079 080 081 082 083 084 085 086 087 088 089 090 091 092 #region 0.DefineVariables $AzurePublishSettingsFile = "C:\Your_Local_Path\Your Windows Azure Subscription Name-MM-DD-YYYY-credentials.publishsettings" $AzureSubscriptionName = "Windows Azure MSDN - Visual Studio Ultimate" $ProjectName = "BCBWFDemo" $ProjectNameLower = $ProjectName.ToLower() $AzureStorageAccountName = $ProjectNameLower $VMName = "{0}-001" -f $ProjectNameLower $ServiceName = $ProjectName $AffinityGroupName = $ProjectName $ImageName = $ProjectName $ProjectCopiedBlobName = "{0}_copy.vhd" -f $ProjectName $ProjectContainerName = $ProjectNameLower $ProjectBlobName = "{0}.vhd" -f $ProjectName $GenericContainerName = "vhds" #endregion 0.DefineVariables #region 1.PrerequisiteSetup #1.0. Perform Prerequisite Setup Steps #1.1. Download latest Windows Azure PowerShell Module: http://go.microsoft.com/?linkid=9811175&clcid=0x409 #1.2. Execute: Get-AzurePublishSettingsFile; Save .publishsettings file locally Get-AzurePublishSettingsFile #1.3. Execute: Import-AzurePublishSettingsFile; reference local .publishsettings file Import-AzurePublishSettingsFile -PublishSettingsFile $AzurePublishSettingsFile #1.4. Execute: Set-AzureSubscription with -CurrentStorageAccountName Set-AzureSubscription -SubscriptionName $AzureSubscriptionName -CurrentStorageAccountName $AzureStorageAccountName Get-AzureSubscription #endregion 1.PrerequisiteSetup #region 2.RemoveVMandImage #Remove Windows Azure VM and Image Remove-AzureVM -Name $VMName -ServiceName $ServiceName Remove-AzureVMImage -ImageName $ImageName #endregion 2.RemoveVMandImage #region 3.RemoveVMDisk #Remove Windows Azure VM Specific Disk do { "Disk Attachments being Removed..." (Get-AzureDisk | where {$_.DiskName -match $ProjectName}).AttachedTo Start-Sleep -Seconds 30 } until ((Get-AzureDisk | where {$_.DiskName -match $ProjectName}).AttachedTo.Length -eq 0) Start-Sleep -Seconds 15 if ((Get-AzureDisk | where {$_.DiskName -match $ProjectName}).AttachedTo.Length -eq 0) { $AzureDiskToRemove = Get-AzureDisk | where {$_.DiskName -match $ProjectName} $AzureDiskToRemove.AttachedTo $AzureDiskToRemove | Remove-AzureDisk } #endregion 3.RemoveVMDisk #region 4.RemoveStorageResources #Remove Windows Azure Storage Account Resources Remove-AzureStorageAccount -StorageAccountName $AzureStorageAccountName <# #The lower level Storage Resources (Blobs and Containers) are Removed by the Remove-AzureStorageAccount Command above #For Reference, here are examples of the commands to remove these lower level Storage Resources: #Remove Windows Azure Storage Blobs Remove-AzureStorageBlob -Blob $ProjectCopiedBlobName -Container $ProjectContainerName Remove-AzureStorageBlob -Blob $ProjectBlobName -Container $GenericContainerName #Remove Windows Azure Storage Containers Remove-AzureStorageContainer -Name $ProjectContainerName -Force Remove-AzureStorageContainer -Name $GenericContainerName -Force #> #endregion 4.RemoveStorageResources #region 5.RemoveCloudServiceandAffinityGroup #Remove Windows Azure Cloud Service and Affinity Group Remove-AzureService -ServiceName $ServiceName -Force Remove-AzureAffinityGroup -Name $AffinityGroupName #endregion 5.RemoveCloudServiceandAffinityGroup

Note Since it worked out so nicely last time, I broke the “all together” script into collapsible regions.

Important “Automation” of these Deprovision tasks is very destructive and should be done with care. In fact, I would recommend only executing these script examples one region at at time (if not more granular) to ensure no accidental removal of resources occurs.


Remove Windows Azure Subscription

In the spirit of “Removal”, here is a little script I use when I want to clear out the Selected/Set Windows Azure Subscription from the machine performing all the Windows Azure PowerShell commands:

001 002 003 004 005 006 007 008 009 010 #Remove Windows Azure Subscription (if selected/set) $AzureSubscriptionName = Get-AzureSubscription if ($AzureSubscriptionName) { Remove-AzureSubscription -SubscriptionName $AzureSubscriptionName.SubscriptionName -Force } #Verify Windows Azure Subscription Removal Get-AzureSubscription

Note I intentionally did not included this example script in the above “all together” section. I am not actually sure how often it will be used, but I wanted to provide it just in case.

Execution Results

image


What’s next?

Well, that is it for this Blog Series on Hybrid Cloud Automation with Windows Azure and PowerShell.

All that is left to do, is start exploring and developing use cases to leverage the example scripts within Parts 2, 3 and 4!


Automating Hybrid Clouds with Windows Azure and PowerShell - Blog Series - Table of Contents

I broke this “Automating Windows Azure” topic up into four posts – primarily to make it easier to reference externally (based on varied interest levels).

As promised, the following is the link to the TechNet Contribution and Download for the examples (from all parts of the blog series).


TechNet Contribution and Download

The download (Hybrid Cloud Automation Toolkit - Windows Azure and PowerShell.zip) includes the following (4) files:

  • Provision-WindowsAzureEnvironmentResources.ps1
  • Provision-WindowsAzureEnvironmentResources-Workflow.ps1
  • Deprovision-WindowsAzureEnvironmentResources.ps1
  • Provision-Deprovision-Extras.ps1

Download the Hybrid Cloud Automation Toolkit - Windows Azure and PowerShell from TechNet Gallery here:

BC-DLButtonDark


Thanks for checking out this blog series! For more information, tips/tricks, and example solutions for Automation within System Center, Windows Azure Pack, Windows Azure, etc., be sure to check out the other blog posts from Building Clouds in the Automation Track!

enJOY!