Automation–Automating Hybrid Clouds with Windows Azure and PowerShell (Part 2): Public Cloud Environment Provisioning PowerShell Examples
Hello Again!
Time for Part 2 of the Automating Hybrid Clouds with Windows Azure and PowerShell blog series (find Part 1: Intro & TOC here). And yes, this post actually has PowerShell Examples! But first, the list of what examples will be provided…
Public Cloud Environment Provisioning PowerShell Examples
As covered in the intro post of the blog series, the following is the list of high level concept commands that will be covered in this post:
High Level Concept Commands
- Establish Windows Azure Subscription Connection
- Create Windows Azure Affinity Group
- Create Windows Azure Cloud Service
- Create Windows Azure Storage Account
- Create Windows Azure Storage Container
- Upload “On-Prem” VHD to Windows Azure Storage Container
- Copy Windows Azure Blob
- Create Windows Azure VM Image
- Create Windows Azure VM
Pre-Requisites
Here is the short list of pre-requisites for this example solution:
- Windows Server
- A VHD file that meets the requirements to be uploaded to Windows Azure
Also see: Converting Hyper-V .vhdx to .vhd file formats for use in Windows Azure - Windows Azure PowerShell Module
Direct Download Link: https://go.microsoft.com/?linkid=9811175&clcid=0x409
Establish Windows Azure Subscription Connection
Automation often requires “trust”, especially between two endpoints in any given process/scenario solution. This example is no exception. The connection between the “On-Prem” Windows Server and Windows Azure need to share a “trust”. For Windows Azure (and for this example), one of the most common ways to accomplish this is through “the certificate method” (outlined in this Windows Azure tutorial: How to install and configure Windows Azure PowerShell).
Basically, it leverages the following:
- The Get-AzurePublishSettingsFile cmdlet opens a web page on the Windows Azure Management Portal, from which you can download the subscription information. The information is contained in a .publishsettings file.
- The Import-AzurePublishSettingsFile imports the .publishsettings file for use by the module. This file includes a management certificate that has security credentials.
Example Script (with some instructional comments)
001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 | #0.0. Perform Prerequisite Setup Steps #0.1. Download latest Windows Azure PowerShell Module: https://go.microsoft.com/?linkid=9811175&clcid=0x409 #0.2. Execute: Get-AzurePublishSettingsFile; Save .publishsettings file locally Get-AzurePublishSettingsFile #0.3. Execute: Import-AzurePublishSettingsFile; reference local .publishsettings file $AzurePublishSettingsFile = "C:\Your_Local_Path\Your Windows Azure Subscription Name-MM-DD-YYYY-credentials.publishsettings" Import-AzurePublishSettingsFile -PublishSettingsFile $AzurePublishSettingsFile #0.4. Execute: Set-AzureSubscription and Select-AzureSubscription (and then, to verify Execute: Get-AzureSubscription) $AzureSubscriptionName = "Windows Azure MSDN - Visual Studio Ultimate" Set-AzureSubscription -SubscriptionName $AzureSubscriptionName Select-AzureSubscription -SubscriptionName $AzureSubscriptionName Get-AzureSubscription |
Note I recommend running these commands individually (not all at once) by the groups above.
Execution Results
As part of this process, you will notice a new Management Certificate in the Windows Azure Portal:
If everything was successful, the Get-AzureSubscription results should look similar to this:
Connection Established – Moving On…
Now that we have established a good connection to Windows Azure, we can take care of the rest of the automated steps to build out the environment.
Reminder Obviously, there are other methods and concepts to be automated for Windows Azure - these are just the ones I chose for the examples in this blog series.
Setting up the Environment with a “Project Name”
There is one variable that impacts the entire script and resulting environment. This needs to be set first, and will be used throughout:
- $ProjectName: This is the over-arching variable that will be used (in part or whole) throughout the example. Many other variables are set based on this value.
001 | $ProjectName = "BCBDemo" |
Note If you run this example all the way through as a test, you will see how pervasive this variable’s value actually is. Even if you just look through the “Execution Results” from each step it is apparent. This is for example purposes only. I wanted to simplify the scripts and number of variable inputs.
Create Windows Azure Affinity Group
First step for these examples is to create a Windows Azure Affinity Group within Windows Azure for the environment being built. There is one variable that you will want to consider updating to fit your environmental needs/requirements:
- $AGLocation: The Location the Affinity Group for this Environment/Project is associated with.
001 002 003 004 005 006 007 008 009 010 011 012 | $AGName = $ProjectName $AGLocation = "West US" $AGLocationDesc = "Affinity group for $ProjectName VMs" $AGLabel = "$AGLocation $ProjectName" $AzureAffinityGroup = Get-AzureAffinityGroup -Name $ProjectName -ErrorAction SilentlyContinue if(!$AzureAffinityGroup) { $AzureAffinityGroup = New-AzureAffinityGroup -Location $AGLocation -Name $ProjectName -Description $AGLocationDesc -Label $AGLabel } $AzureAffinityGroup |
Note All variable values were chosen for this example only, and can be changed to fit your project needs.
Execution Results
Create Windows Azure Cloud Service
Next up, is to create a Windows Azure Cloud Service within Windows Azure for the environment being built. There are no new unique variables that require value updates.
001 002 003 004 005 006 007 008 009 010 | $CloudServiceDesc = "Service for $ProjectName VMs" $CloudServiceLabel = "$ProjectName VMs" $AzureService = Get-AzureService -ServiceName $ProjectName -ErrorAction SilentlyContinue if(!$AzureService) { $AzureService = New-AzureService -AffinityGroup $AGName -ServiceName $ProjectName -Description $CloudServiceDesc -Label $CloudServiceLabel } Return $AzureService |
Note This portion of the script depends on the previous two.
Execution Results
Create Windows Azure Storage Account
Next, is to create a Windows Azure Storage Account within Windows Azure for the environment being built. There are no new unique variables that require value updates.
001 002 003 004 005 006 007 008 009 010 011 | $StorageAccountName = $ProjectName.ToLower() $StorageAccountDesc = "Storage account for $ProjectName VMs" $StorageAccountLabel = "$ProjectName Storage" $AzureStorageAccount = Get-AzureStorageAccount -StorageAccountName $StorageAccountName -ErrorAction SilentlyContinue if(!$AzureStorageAccount) { $AzureStorageAccount = New-AzureStorageAccount -AffinityGroup $AGName -StorageAccountName $StorageAccountName -Description $StorageAccountDesc -Label $StorageAccountLabel } $AzureStorageAccount |
Note This portion of the script depends on the previous three.
Execution Results
Create Windows Azure Storage Container(s)
Next, is to create Two Windows Azure Storage Containers within Windows Azure for the environment being built. There are no new unique variables that require value updates.
Reason for Two Storage Containers
- Storage Container #1: Generic VHD Storage Container – “On-Prem” VHD will be uploaded to this container
- Storage Container #2: Project Specific Storage Container – Uploaded VHD will be copied here (this is the VHD that will be leveraged for the rest of the example)
Note Creation of two Storage Containers in this example was to ensure I always had a “known good” copy of the uploaded VHD/Blob.
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 | #Ensure Storage Account is fully created - Sleep for 60 seconds Start-Sleep -Seconds 60 #Update the Azure Subscription Connection with the Storage Account #This makes it easier to connect to the storage account, without requiring the creation and usage of Storage Context $AzureStorageAccountName = $ProjectName.ToLower() Set-AzureSubscription -SubscriptionName $AzureSubscriptionName -CurrentStorageAccount $AzureStorageAccountName #Create Generic VHD Storage Container; VHD will be uploaded here $GenericStorageContainerName = "vhds" #Create Project Storage Container; VHD will be copied here $ProjectStorageContainerName = $ProjectName.ToLower() $StorageContainerNames = @($GenericStorageContainerName,$ProjectStorageContainerName) foreach ($StorageContainerName in $StorageContainerNames) { $AzureStorageContainer = Get-AzureStorageContainer -Name $StorageContainerName -ErrorAction SilentlyContinue if(!$AzureStorageContainer) { $AzureStorageContainer = New-AzureStorageContainer -Name $StorageContainerName } $AzureStorageContainer } |
Note This portion of the script depends on the previous four.
Execution Results
Upload “On-Prem” VHD to Windows Azure Storage Container
Next, is to upload the “On-Prem” VHD to the Generic Windows Azure Storage Container within Windows Azure for the environment being built. This portion of PowerShell does require some customization, as it references the previously mentioned, “…VHD file that meets the requirements to be uploaded to Windows Azure”:
- $SourceDiskName: The Name of the VHD (without .vhd extension) to be uploaded to the Generic Windows Azure Storage Container.
- $SourceDiskPath: The Path of the VHD (without trailing "\") to be uploaded to the Generic Windows Azure Storage Container.
001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 | #Set Source VHD Info $SourceDiskName = "toWindowsAzure" $SourceDiskFileExt = "vhd" $SourceDiskPath = "D:\Drop\Azure\toAzure" $SourceVHDName = "{0}.{1}" -f $SourceDiskName,$SourceDiskFileExt $SourceVHDPath = "{0}\{1}" -f $SourceDiskPath,$SourceVHDName #Set Destination Blob Info $DesitnationVHDName = "{0}.{1}" -f $ProjectName,$SourceDiskFileExt $DestinationVHDPath = "https://{0}.blob.core.windows.net/{1}" -f $AzureStorageAccountName,$GenericStorageContainerName $DestinationBlobURI = "{0}/{1}" -f $DestinationVHDPath,$DesitnationVHDName $OverWrite = $false #Upload Local VHD to the Generic VHD Windows Azure Storage Container; this will take a while $AzureBlob = Get-AzureStorageBlob -Container $GenericStorageContainerName -Blob $DesitnationVHDName -ErrorAction SilentlyContinue if(!$AzureBlob -or $OverWrite) { $AzureBlob = Add-AzureVhd -LocalFilePath $SourceVHDPath -Destination $DestinationBlobURI -OverWrite:$OverWrite } $AzureBlob |
Note This portion of the script depends on the previous five.
The following is an image (not that it is really needed, but for proof) , of the file and path of the VHD I am uploading in this example:
Execution Results
Because this step takes a while, when you run the example PowerShell above, you have the opportunity to see the ongoing status within the PowerShell console. Here is a screenshot of the process, mid-execution:
Note Over a fast connection, a file of this size (7.5GB) takes about 10 minutes to upload (as seen in the results below).
Copy Windows Azure Blob
Next, is to copy the uploaded VHD (now a Windows Azure Blob) from the Generic Container (vhds) to the Project Specific Container within Windows Azure for the environment being built. There are no new unique variables that require value updates.
Note Usage of two Storage Containers in this example was to ensure I always had a “known good” copy of the uploaded VHD/Blob.
001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 | #Set Source Blob Info for Copy $SourceBlobName = $DesitnationVHDName $SourceContainer = $GenericStorageContainerName #Set Destination Blob Info for Copy $DestinationContainer = $ProjectStorageContainerName $DestinationBlobName = "{0}_copy.{1}" -f $ProjectName,$SourceDiskFileExt $CopiedAzureBlob = Get-AzureStorageBlob -Container $DestinationContainer -Blob $DestinationBlobName -ErrorAction SilentlyContinue #Copy Uploaded Blob from Generic to Project if(!$CopiedAzureBlob) { $CopiedAzureBlob = Start-AzureStorageBlobCopy -DestContainer $DestinationContainer -SrcBlob $SourceBlobName -SrcContainer $SourceContainer -DestBlob $DestinationBlobName } Return $CopiedAzureBlob |
Note This portion of the script depends on the previous six.
Execution Results
Create Windows Azure VM Image
Next, is to create an Azure VM Image from copied blob within Windows Azure for the environment being built. There are no new unique variables that require value updates as $VMImageOS likely will remain “Windows” for the VHDs uploaded.
001 002 003 004 005 006 007 008 009 010 011 012 013 014 | $VMImageName = $ProjectName $VMImageBlobContainer = $DestinationContainer $VMImageBlobName = $DestinationBlobName $VMImageOS = "Windows" $AzureVMImage = Get-AzureVMImage -ImageName $VMImageName -ErrorAction SilentlyContinue if(!$AzureVMImage) { $AzureBlobMediaLocation = (Get-AzureStorageBlob -Container $VMImageBlobContainer -Blob $VMImageBlobName).ICloudBlob.Uri.AbsoluteUri $AzureVMImage = Add-AzureVMImage -ImageName $VMImageName -MediaLocation $AzureBlobMediaLocation -OS $VMImageOS } Return $AzureVMImage |
Note This portion of the script depends on the previous seven.
Execution Results
Create Windows Azure VM
Next, (what we all have been waiting for!) is to create a Windows Azure VM from the Windows Azure VM Image within Windows Azure for the environment being built. This portion of PowerShell does require some customization:
- $VMName: The Name of the VM being created – the example I show here is a simple numbering suffix. It is not a mask of any kind, but something that generates a sequencing integer could be created. If you are uploading a large number of VM to create Windows Azure VMs, you would likely be referencing VM Name (and most other things) from an external data source. Either way, it is up to you, this is just example naming.
- $AdminUsername: The Name of the Admin User for initial login to the Windows Azure VM. This cannot be "Administrator".
- $Password: The Password for the Admin User for initial login to the Windows Azure VM.
- $Windows: The OS of Windows Azure VM. Again, this will likely remain “Windows” for the VHDs uploaded.
- $VMInstanceSize: The VM Instance Size for the Windows Azure VM (options available, reference the following: Virtual Machine and Cloud Service Sizes for Windows Azure).
- $WaitForBoot: The option to wait for the Windows Azure VM to finish "Provisioning" before releasing control back to the PowerShell console.
001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 | $VMName = "{0}-001" -f $ProjectName.ToLower() $ServiceName = $ProjectName $AdminUsername = "AdminUser" $VMImageName = $AzureVMImage.ImageName $Password = "Pass@word1" $Windows = $true $VMInstanceSize = "ExtraSmall" $WaitForBoot = $true $AzureVM = Get-AzureVM -Name $VMName -ServiceName $ServiceName -ErrorAction SilentlyContinue if(!$AzureVM -and $Windows) { $AzureVM = New-AzureQuickVM -AdminUsername $AdminUsername -ImageName $VMImageName -Password $Password ` -ServiceName $ServiceName -Windows:$Windows -InstanceSize $VMInstanceSize -Name $VMName -WaitForBoot:$WaitForBoot } Return $AzureVM |
Note This portion of the script depends on the previous eight. Also, the method used to create the Windows Azure VM in this example was New-AzureQuickVM, there are other methods – Please see some examples below (after the "Putting it all together" section).
Execution Results
Because this step takes a while, you have the opportunity to see the ongoing status within the Windows Azure Portal. Here is a screenshot of the Windows Azure VM creation, mid-execution:
Note "Provisioning" durations vary.
Connecting to the Windows Azure VM
Once provisioned, it is simple to connect directly to the Windows Azure VM to test its contents.
Step 1: Select the Windows Azure VM, Click Connect
Step 2: When prompted, Open the RDP file that is presented
Step 3: When prompted, Enter the credentials you provided within the Create Windows Azure VM PowerShell Script
Step 4: Wait for the RDP Session to complete and connect you to the Windows Azure VM
Step 5: Use/Explore the Windows Azure VM
Note Obviously nothing was done to customize the network for this VM. Windows Azure Virtual Network was out of scope for this example. For more information, please refer to the following: Windows Azure Virtual Network Overview .
A Dashboard View of the created Windows Azure VM
Putting it all together
I realize this is more than “like 5 lines of PowerShell”. But in reality, if you had the Windows Azure environment already created, that number isn’t that far off. Either way, here are all the above PowerShell script portions, rolled up into one script example:
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 093 094 095 096 097 098 099 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 | #0.0. Perform Prerequisite Setup Steps #0.1. Download latest Windows Azure PowerShell Module: https://go.microsoft.com/?linkid=9811175&clcid=0x409 #0.2. Execute: Get-AzurePublishSettingsFile; Save .publishsettings file locally Get-AzurePublishSettingsFile #0.3. Execute: Import-AzurePublishSettingsFile; reference local .publishsettings file $AzurePublishSettingsFile = "C:\Your_Local_Path\Your Windows Azure Subscription Name-MM-DD-YYYY-credentials.publishsettings" Import-AzurePublishSettingsFile -PublishSettingsFile $AzurePublishSettingsFile #0.4. Execute: Set-AzureSubscription and Select-AzureSubscription (and then, to verify Execute: Get-AzureSubscription) $AzureSubscriptionName = "Windows Azure MSDN - Visual Studio Ultimate" Set-AzureSubscription -SubscriptionName $AzureSubscriptionName Select-AzureSubscription -SubscriptionName $AzureSubscriptionName Get-AzureSubscription #1.0 Setting up the Environment with a “Project Name” $ProjectName = "BCBDemo" #2.0 Create Windows Azure Affinity Group $AGName = $ProjectName $AGLocation = "West US" $AGLocationDesc = "Affinity group for $ProjectName VMs" $AGLabel = "$AGLocation $ProjectName" $AzureAffinityGroup = Get-AzureAffinityGroup -Name $ProjectName -ErrorAction SilentlyContinue if(!$AzureAffinityGroup) { $AzureAffinityGroup = New-AzureAffinityGroup -Location $AGLocation -Name $ProjectName -Description $AGLocationDesc -Label $AGLabel } $AzureAffinityGroup #3.0 Create Windows Azure Cloud Service $CloudServiceDesc = "Service for $ProjectName VMs" $CloudServiceLabel = "$ProjectName VMs" $AzureService = Get-AzureService -ServiceName $ProjectName -ErrorAction SilentlyContinue if(!$AzureService) { $AzureService = New-AzureService -AffinityGroup $AGName -ServiceName $ProjectName -Description $CloudServiceDesc -Label $CloudServiceLabel } Return $AzureService #4.0 Create Windows Azure Storage Account $StorageAccountName = $ProjectName.ToLower() $StorageAccountDesc = "Storage account for $ProjectName VMs" $StorageAccountLabel = "$ProjectName Storage" $AzureStorageAccount = Get-AzureStorageAccount -StorageAccountName $StorageAccountName -ErrorAction SilentlyContinue if(!$AzureStorageAccount) { $AzureStorageAccount = New-AzureStorageAccount -AffinityGroup $AGName -StorageAccountName $StorageAccountName -Description $StorageAccountDesc -Label $StorageAccountLabel } $AzureStorageAccount #5.0 Create Windows Azure Storage Container(s) #Ensure Storage Account is fully created - Sleep for 60 seconds Start-Sleep -Seconds 60 #Update the Azure Subscription Connection with the Storage Account #This makes it easier to connect to the storage account, without requiring the creation and usage of Storage Context $AzureStorageAccountName = $ProjectName.ToLower() Set-AzureSubscription -SubscriptionName $AzureSubscriptionName -CurrentStorageAccount $AzureStorageAccountName #Create Generic VHD Storage Container; VHD will be uploaded here $GenericStorageContainerName = "vhds" #Create Project Storage Container; VHD will be copied here $ProjectStorageContainerName = $ProjectName.ToLower() $StorageContainerNames = @($GenericStorageContainerName,$ProjectStorageContainerName) foreach ($StorageContainerName in $StorageContainerNames) { $AzureStorageContainer = Get-AzureStorageContainer -Name $StorageContainerName -ErrorAction SilentlyContinue if(!$AzureStorageContainer) { $AzureStorageContainer = New-AzureStorageContainer -Name $StorageContainerName } $AzureStorageContainer } #6.0 Upload “On-Prem” VHD to Windows Azure Storage Container #Set Source VHD Info $SourceDiskName = "toWindowsAzure" $SourceDiskFileExt = "vhd" $SourceDiskPath = "D:\Drop\Azure\toAzure" $SourceVHDName = "{0}.{1}" -f $SourceDiskName,$SourceDiskFileExt $SourceVHDPath = "{0}\{1}" -f $SourceDiskPath,$SourceVHDName #Set Destination Blob Info $DesitnationVHDName = "{0}.{1}" -f $ProjectName,$SourceDiskFileExt $DestinationVHDPath = "https://{0}.blob.core.windows.net/{1}" -f $AzureStorageAccountName,$GenericStorageContainerName $DestinationBlobURI = "{0}/{1}" -f $DestinationVHDPath,$DesitnationVHDName $OverWrite = $false #Upload Local VHD to the Generic VHD Windows Azure Storage Container; this will take a while $AzureBlob = Get-AzureStorageBlob -Container $GenericStorageContainerName -Blob $DesitnationVHDName -ErrorAction SilentlyContinue if(!$AzureBlob -or $OverWrite) { $AzureBlob = Add-AzureVhd -LocalFilePath $SourceVHDPath -Destination $DestinationBlobURI -OverWrite:$OverWrite } $AzureBlob #7.0 Copy Windows Azure Blob #Set Source Blob Info for Copy $SourceBlobName = $DesitnationVHDName $SourceContainer = $GenericStorageContainerName #Set Destination Blob Info for Copy $DestinationContainer = $ProjectStorageContainerName $DestinationBlobName = "{0}_copy.{1}" -f $ProjectName,$SourceDiskFileExt $CopiedAzureBlob = Get-AzureStorageBlob -Container $DestinationContainer -Blob $DestinationBlobName -ErrorAction SilentlyContinue #Copy Uploaded Blob from Generic to Project if(!$CopiedAzureBlob) { $CopiedAzureBlob = Start-AzureStorageBlobCopy -DestContainer $DestinationContainer -SrcBlob $SourceBlobName -SrcContainer $SourceContainer -DestBlob $DestinationBlobName } Return $CopiedAzureBlob #8.0 Create Windows Azure VM Image $VMImageName = $ProjectName $VMImageBlobContainer = $DestinationContainer $VMImageBlobName = $DestinationBlobName $VMImageOS = "Windows" $AzureVMImage = Get-AzureVMImage -ImageName $VMImageName -ErrorAction SilentlyContinue if(!$AzureVMImage) { $AzureBlobMediaLocation = (Get-AzureStorageBlob -Container $VMImageBlobContainer -Blob $VMImageBlobName).ICloudBlob.Uri.AbsoluteUri $AzureVMImage = Add-AzureVMImage -ImageName $VMImageName -MediaLocation $AzureBlobMediaLocation -OS $VMImageOS } Return $AzureVMImage #9.0 Create Windows Azure VM $VMName = "{0}-001" -f $ProjectName.ToLower() $ServiceName = $ProjectName $AdminUsername = "AdminUser" $VMImageName = $AzureVMImage.ImageName $Password = "Pass@word1" $Windows = $true $VMInstanceSize = "ExtraSmall" $WaitForBoot = $true $AzureVM = Get-AzureVM -Name $VMName -ServiceName $ServiceName -ErrorAction SilentlyContinue if(!$AzureVM -and $Windows) { $AzureVM = New-AzureQuickVM -AdminUsername $AdminUsername -ImageName $VMImageName -Password $Password ` -ServiceName $ServiceName -Windows:$Windows -InstanceSize $VMInstanceSize -Name $VMName -WaitForBoot:$WaitForBoot } Return $AzureVM |
Alternate Windows Azure VM Create Examples
Note As stated above, the method used to create the Windows Azure VM in this example was New-AzureQuickVM, there are other methods – Please see the following for a couple of those alternate methods.
001 002 003 004 005 006 007 008 009 010 | #Alternate Windows Azure VM Create: Example #1 New-AzureVMConfig -DiskName $DiskName -InstanceSize $VMInstanceSize -Name $VMName | ` Add-AzureProvisioningConfig -AdminUsername $AdminUsername -Windows -Password $Password -ResetPasswordOnFirstLogon | ` New-AzureVM –ServiceName $ServiceName #Alternate Windows Azure VM Create: Example #2 $VMConfig = New-AzureVMConfig -Name $VMName -InstanceSize $VMInstanceSize -ImageName $VMImageName | ` Add-AzureProvisioningConfig -Windows -Password $Password -AdminUsername $AdminUsername New-AzureVM -ServiceName $ServiceName -VMs $VMConfig –WaitForBoot |
Community Built Alternate Windows Azure VM Create Example!
I would like to take the time to share something that came from the MVP Community recently – Another Alternate Windows Azure VM Creation Example… (Thank you Christopher Keyaert!)
This example highlights the ability to create a Windows Azure VM from a Disk with a VNet and Subnet defined.
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 | ######################################################## # Define Parameters ######################################################## $ProjectName = "TestProj" $SourceDiskFileExt = "vhd" $VMInstanceSize = "ExtraSmall" $VMImageOS = "Windows" $BlobName = "{0}_copy.{1}" -f $ProjectName,$SourceDiskFileExt $BlobContainer = $ProjectName.ToLower() $DiskName = "{0}-001" -f $ProjectName.ToLower() $DiskLabel = "BootDisk" $VNetSiteName = "VNetSiteName" $SubNetName = "SubnetName" $Windows = $true $ServiceName = $ProjectName $VMName = "{0}-001" -f $ProjectName.ToLower() ######################################################## # Add a new Disk to the Windows Azure Disk Repository ######################################################## $AzureBlobMediaLocation = (Get-AzureStorageBlob -Container $BlobContainer -Blob $BlobName).ICloudBlob.Uri.AbsoluteUri Add-AzureDisk -DiskName $DiskName -MediaLocation $AzureBlobMediaLocation -Label $DiskLabel -OS $VMImageOS ######################################################## # Get Windows Azure VNet and Subnet Information ######################################################## $AzureVNet = Get-AzureVNetSite | where {$_.Name -eq $VNetSiteName} $AzureSubNet = $AzureVNet.Subnets | where {$_.Name -eq $SubNetName} ######################################################## #Create Windows Azure VM from Disk with VNet and Subnet ######################################################## $AzureVM = Get-AzureVM -Name $VMName -ServiceName $ServiceName -ErrorAction SilentlyContinue if(!$AzureVM -and $Windows) { $VMConfig = New-AzureVMConfig -Name $VMName -InstanceSize $VMInstanceSize -DiskName $VMName | Set-AzureSubnet $AzureSubNet.Name New-AzureVM -ServiceName $ServiceName -VMs $VMConfig -VNetName $AzureVNet.Name –WaitForBoot } Return $AzureVM |
Note This is an example that builds on the other scripts within this blog post. Be sure you have all pre-requisite steps completed before you attempt to implement this example.
Important If you attempt to create a new Windows Azure VM in an existing deployment with the above script you will likely get a warning like this:
Warning Text: WARNING: VNetName, DnsSettings, DeploymentLabel or DeploymentName Name can only be specified on new deployments.
Execution Results
Once again, a big Thanks to Christopher for expanding on what I published here and suggesting that I share it with the rest of the community!
Other Learnings
During the "Conversion" process from Orchestrator Runbooks to Windows PowerShell, I ran up against a few things that I had to figure out. Here are a two of those learnings (outside what you have seen above), for just in case:
Storage Context
Before I learned about Setting the Azure Subscription with a "Current Storage Account", I tried my hand at creating and leveraging a Storage Context. Once you have created a Storage Context, you can reference it and pass it as a variable to commands requiring some level of specificity when it comes to Windows Azure Storage. While I did not use Storage Context in the examples above, I figured I would give you some example PowerShell, if you decide that is the route you want to take:
001 002 003 004 005 | #Get Azure Storage Key and Create New Azure Storage Context if(!$AzureStorageContext) { $AzureStorageKey = Get-AzureStorageKey -StorageAccountName $StorageAccountName $AzureStorageContext = New-AzureStorageContext -StorageAccountKey $AzureStorageKey.Primary -StorageAccountName $StorageAccountName } |
References
- New-AzureStorageContext (Windows Azure Documentation for this command)
- Get-AzureStorageContainer and Get-AzureStorageBlob (example usage of Storage Context from the Windows Azure Documentation)
Digging Deeper: Bad Request (400)
I ran into quite a few exceptions during the build out of this example solution. Needless to say, when the PowerShell screen turns red, frustration rises just a little bit (if not more than a little bit). The following command helped me dig deeper on some of the more vague errors being returned by the command failure exceptions:
001 002 003 | #Read Full Error Stream from Failed [Windows Azure] Command $ErrorStream = New-Object System.IO.StreamReader($Error[0].Exception.InnerException.Response.GetResponseStream()) $ErrorStream.ReadToEnd() |
Note While it will not work in all cases, and while it is very generic, I found that if this is run right after a "Bad Request (400)", the "InnerText" of the Exception helped tremendously with what was actually going on. I found this originally referenced here .
Exception Handling Improved?
To get some proof of this working, I attempted to recreate the scenario where I needed to use the above commands. In my attempt to reproduce the "Bad Request (400)", I was met with actually useful and accurate errors:
That’s it! If I have any more learnings, I will add them to the upcoming blog posts.
What’s next?
So, what’s next? On to increasing complexity – Part 3 of this blog series takes what we have in this post, and transports it to a new world – Windows PowerShell Workflow!
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).
- Automation–Automating Hybrid Clouds with Windows Azure and PowerShell (Part 1): Introduction and Table of Contents
- Automation–Automating Hybrid Clouds with Windows Azure and PowerShell (Part 2): Public Cloud Environment Provisioning PowerShell Examples
- Automation–Automating Hybrid Clouds with Windows Azure and PowerShell (Part 3): Public Cloud Environment Provisioning PowerShell Workflow Examples
- Automation–Automating Hybrid Clouds with Windows Azure and PowerShell (Part 4): Public Cloud Environment Deprovisioning PowerShell Examples
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
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!
Comments
Anonymous
November 19, 2013
Hi Charles, Thank you for your post and sharing all this info ! Just a link about how to convert a VHDX to VHD for Azure with PowerShell blogs.technet.com/.../converting-hyper-v-vhdx-to-vhd-file-formats-for-use-in-windows-azure.aspx Thx ChristopherAnonymous
November 19, 2013
The comment has been removedAnonymous
November 19, 2013
Great :-) Do you see any blocking point to not consume your script with SMA ? Could be a great solution to replace App Controller.Anonymous
November 20, 2013
The comment has been removedAnonymous
January 08, 2014
Over the last three “Best Practices” posts, I’ve looked at how to Plan , Build , and Deploy a HybridAnonymous
January 09, 2014
Over the last three “Best Practices” posts, I’ve looked at how to Plan , Build , and Deploy a HybridAnonymous
March 24, 2014
在前三篇“最佳实践”文章中,我们讨论了如何 规划 、 构建 和 部署 混合云 – 既然混合云已经上线运行,接下来该看看如何 保持 它始终在最佳状态下运行,并提供高性能Anonymous
October 10, 2014
Automation–Automating Hybrid Clouds with Windows Azure and PowerShell (Part 2): Public Cloud Environment Provisioning PowerShell Examples - Building Clouds Blog - Site Home - TechNet BlogsAnonymous
October 10, 2014
Automation–Automating Hybrid Clouds with Windows Azure and PowerShell (Part 2): Public Cloud Environment Provisioning PowerShell Examples - Building Clouds Blog - Site Home - TechNet BlogsAnonymous
October 10, 2014
Automation–Automating Hybrid Clouds with Windows Azure and PowerShell (Part 2): Public Cloud Environment Provisioning PowerShell Examples - Building Clouds Blog - Site Home - TechNet BlogsAnonymous
October 11, 2014
Automation–Automating Hybrid Clouds with Windows Azure and PowerShell (Part 2): Public Cloud Environment Provisioning PowerShell Examples - Building Clouds Blog - Site Home - TechNet BlogsAnonymous
October 12, 2014
Automation–Automating Hybrid Clouds with Windows Azure and PowerShell (Part 2): Public Cloud Environment Provisioning PowerShell Examples - Building Clouds Blog - Site Home - TechNet BlogsAnonymous
October 12, 2014
Automation–Automating Hybrid Clouds with Windows Azure and PowerShell (Part 2): Public Cloud Environment Provisioning PowerShell Examples - Building Clouds Blog - Site Home - TechNet BlogsAnonymous
October 13, 2014
Automation–Automating Hybrid Clouds with Windows Azure and PowerShell (Part 2): Public Cloud Environment Provisioning PowerShell Examples - Building Clouds Blog - Site Home - TechNet BlogsAnonymous
October 14, 2014
Automation–Automating Hybrid Clouds with Windows Azure and PowerShell (Part 2): Public Cloud Environment Provisioning PowerShell Examples - Building Clouds Blog - Site Home - TechNet BlogsAnonymous
October 25, 2014
Automation–Automating Hybrid Clouds with Windows Azure and PowerShell (Part 2): Public Cloud Environment Provisioning PowerShell Examples - Building Clouds Blog - Site Home - TechNet BlogsAnonymous
October 28, 2014
Automation–Automating Hybrid Clouds with Windows Azure and PowerShell (Part 2): Public Cloud Environment Provisioning PowerShell Examples - Building Clouds Blog - Site Home - TechNet BlogsAnonymous
November 03, 2014
Automation–Automating Hybrid Clouds with Windows Azure and PowerShell (Part 2): Public Cloud Environment Provisioning PowerShell Examples - Building Clouds Blog - Site Home - TechNet BlogsAnonymous
November 25, 2014
Automation–Automating Hybrid Clouds with Windows Azure and PowerShell (Part 2): Public Cloud Environment Provisioning PowerShell Examples - Building Clouds Blog - Site Home - TechNet Blogs