Skip to content

Instantly share code, notes, and snippets.

@pkirch
Last active August 29, 2015 14:14
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pkirch/695eb59a532265a5dd55 to your computer and use it in GitHub Desktop.
Save pkirch/695eb59a532265a5dd55 to your computer and use it in GitHub Desktop.
Script for IT Camp Hybrid IT.
# Script created by Peter Kirchner (peter.kirchner@microsoft.com); changed last on 23.04.2015. Based on script by Patrick Heyde (patrick.heyde@microsoft.com).
# The most current version of this script can be found at GitHub Gist: https://gist.github.com/pkirch/695eb59a532265a5dd55
# Description:
# This script sample is part of the IT Camps Hybrid IT in Germany.
# This script copies VHDs from a source storage account into a destination storage account,
# registers the VHDs as disks, imports VM configuration files and starts the VMs.
# Finally the script creates a subfolder in the configuration files folder and stores
# RDP files to the newly created VMs.
#region Settings
# Name of the Azure subscription, where the new System Center infrastructure should be created.
$subscriptionName = "MSFT IT Camp Stage"
# Path to VM configurations files. (See http://pkit.azurewebsites.net for download link.)
$pathConfigFiles = "C:\Users\pkirch\OneDrive @ Microsoft\FY15\Content\2015-01 IT Camp\vms"
# Name of your virtual network, which contains the following subnets: Subnet-0, Subnet-1, Subnet-2, and Subnet-3.
$vNetName = "pkbackup"
# Name of your cloud service.
$cloudServiceName = "pkbackup"
# Settings for source storage account. (See http://pkit.azurewebsites.net for current access key.)
$sourceStorageAccountName = "itcampfeb15"
$sourceStorageAccountKey = "pKNdyJJECO/ZRfh8WHXY4Bhdj1EdCbIrnq2fjTwJtICVzxh8UFcxLWHZsznvibzonvs4BSO/5Gl+xSyOTJ0PkQ==" # PAK
$sourceStorageContainer = "feb15"
# Settings for destination storage account.
$destinationStorageAccountName = ""
$destinationStorageAccountKey = "" # PAK / SAK
$destinationStorageContainer = "itcamp"
# Settings for copy operation.
$fileFilter = "*.vhd"
# Settings for disk registration.
$namePrefix = "uschl-20150210"
# Set this variable to $true if you have finished all preparations and settings.
$enableScript = $false
if (!$enableScript) {
Write-Warning "Script not enabled yet. No operations executed. Exiting script."
return
}
#endregion
Select-AzureSubscription -SubscriptionName $subscriptionName
#region Copy VHDs.
# Create two storage contexts for source and destination.
$sourceStorageContext = New-AzureStorageContext -StorageAccountName $sourceStorageAccountName -StorageAccountKey $sourceStorageAccountKey
$destinationStorageContext = New-AzureStorageContext -StorageAccountName $destinationStorageAccountName -StorageAccountKey $destinationStorageAccountKey
#region Check storage accounts for same cluster (stamp).
[System.Uri]$sourceBlobEndPoint = New-Object -TypeName System.Uri -ArgumentList $sourceStorageContext.BlobEndPoint
[System.Uri]$destinationBlobEndPoint = New-Object -TypeName System.Uri -ArgumentList $destinationStorageContext.BlobEndPoint
$sourceAddress = [System.Net.Dns]::GetHostAddresses($sourceBlobEndPoint.DnsSafeHost)
$destinationAddress = [System.Net.Dns]::GetHostAddresses($destinationBlobEndPoint.DnsSafeHost)
Write-Host "IP address of source BLOB endpoint: $sourceAddress"
Write-Host "IP address of destination BLOB endpoint: $destinationAddress"
if ($sourceAddress.IPAddressToString -ne $destinationAddress.IPAddressToString) {
Write-Warning "IP addresses of source and destination BLOB endpoint do not match!"
Write-Warning "No operations executed. Exiting script."
return
}
#endregion
# Create destination container if it does not exist.
$destinationContainerList = Get-AzureStorageContainer -Context $destinationStorageContext -Name $destinationStorageContainer -ErrorAction Ignore
if ($destinationContainerList.Length -eq 0) {
Write-Warning "Destination container '$destinationStorageContainer' does not exist. Creating it."
New-AzureStorageContainer -Context $destinationStorageContext -Name $destinationStorageContainer -Permission Off
}
# Copy VHDs from source to destination.
Write-Host "$(Get-Date -Format HH:mm:ss): Copy operation started."
# Get all BLOBs from source container and start copy operation asynchronously for all files based on $fileFilter.
Get-AzureStorageBlob -Context $sourceStorageContext -Container $sourceStorageContainer -Blob $fileFilter |
Start-AzureStorageBlobCopy -DestContext $destinationStorageContext -DestContainer $destinationStorageContainer
# Check copy state in destination container.
$waitTime = 5 # Initial wait time.
do {
# Wait some time before refresh of copy state, except on first iteration.
if ($copyState) {
Write-Host "Refresh in $waitTime seconds."
# After each iteration wait some more time.
Start-Sleep -Seconds ($waitTime++)
}
# Get all BLOBs in destination container and get copy state for all of them.
$copyState = Get-AzureStorageBlob -Context $destinationStorageContext -Container $destinationStorageContainer -Blob $fileFilter |
Get-AzureStorageBlobCopyState
# Print formatted output.
$copyState | Format-Table -Property CopyId, Status, TotalBytes, BytesCopied, @{Name = "Progress"; Expression = {$_.BytesCopied / $_.TotalBytes * 100}; FormatString = "0.00" }, CompletionTime -AutoSize
} while ($copyState.Status -contains "Pending")
Write-Host "$(Get-Date -Format HH:mm:ss): Copy operation finished."
# Stop all copy operations to the destination container.
#Get-AzureStorageBlob -Context $destinationStorageContext -Container $destinationStorageContainer -Blob $fileFilter |
# Stop-AzureStorageBlobCopy
#endregion
#region Register VHDs as disks in Azure Hyper-Visor.
# Create an empty array, which will hold registered disks for all VHDs in the destination container
Write-Host "$(Get-Date -Format HH:mm:ss): Register disks started."
$disks = @() # Create an empty array.
# Get all BLOBs in destination container.
$blobs = Get-AzureStorageBlob -Context $destinationStorageContext -Container $destinationStorageContainer
# Register all OS disks.
$blobs | Where-Object -Property Name -ilike "*.vhd" | Where-Object -Property Name -inotlike "*DataDisk*" |
ForEach-Object {
$disks += Add-AzureDisk -OS Windows -DiskName "$namePrefix$($_.Name)" -MediaLocation "$($_.ICloudBlob.StorageUri.PrimaryUri.AbsoluteUri)" }
#Register all data disks.
$blobs | Where-Object -Property Name -ilike "*DataDisk*.vhd" |
ForEach-Object {
$disks += Add-AzureDisk -DiskName "$namePrefix$($_.Name)" -MediaLocation "$($_.ICloudBlob.StorageUri.PrimaryUri.AbsoluteUri)" }
Write-Host "$(Get-Date -Format HH:mm:ss): Register disks finished."
#endregion
#region Import and start VMs.
Write-Host "$(Get-Date -Format HH:mm:ss): Create VMs and start them."
# Set the current storage account and print out information.
Set-AzureSubscription -SubscriptionName $subscriptionName -CurrentStorageAccountName $destinationStorageAccountName -PassThru |
Format-List -Property Name, Id, Account, @{Name = "Current Storage Account"; Expression = {$_.Properties["StorageAccount"]}}
# Load config files for VMs.
$configFiles = Get-ChildItem -Path $pathConfigFiles
# Define systems in order of creation associated with subnets.
$systemsITCamp = [ordered]@{ DC = @{SubnetName = "Subnet-0"};
SQL01 = @{SubnetName = "Subnet-2"};
SC01 = @{SubnetName = "Subnet-1"};
SC02 = @{SubnetName = "Subnet-1"};
SC03 = @{SubnetName = "Subnet-1"};
WFE01 = @{SubnetName = "Subnet-3"};
WFE02 = @{SubnetName = "Subnet-3"}}
$systemIDs = @($systemsITCamp.Keys) # Need @() to create a new array; without we only get a reference to the keys array and not values.
# Associate systems with configuration file and OS disk.
foreach ($systemKey in $systemIDs) {
$systemsITCamp[$systemKey].ConfigFile = $configFiles | Where-Object -Property Name -ilike "*$systemKey*" | Select-Object -ExpandProperty FullName -First 1
$systemsITCamp[$systemKey].OSDisk = $disks | Where-Object -Property DiskName -inotlike "*datadisk*" | Where-Object -Property DiskName -ilike "*$systemKey*" | Select-Object -First 1
}
# DC is special and needs two data disks.
$systemsITCamp.DC.DataDisk1 = $disks | Where-Object -Property DiskName -ilike "*dc*datadisk1*" | Select-Object -First 1
$systemsITCamp.DC.DataDisk2 = $disks | Where-Object -Property DiskName -ilike "*dc*datadisk2*" | Select-Object -First 1
Write-Host "Collected configuration for IT Camp"
$systemsITCamp.GetEnumerator() | ForEach-Object {
$config = @{Name = $_.Name; Subnet = $_.Value.SubnetName; ConfigFile = $_.Value.ConfigFile; "OS Disk" = $_.Value.OSDisk.DiskName; "Data Disk 1" = $_.Value.DataDisk1.DiskName; "Data Disk 2" = $_.Value.DataDisk2.DiskName }
New-Object -TypeName PSObject -Property $config
} | Format-List -Property Name, Subnet, ConfigFile, "OS Disk", "Data Disk 1", "Data Disk 2"
# Iterate all defined systems, import config file, adapt imported data, and start VM.
foreach ($system in $systemsITCamp.GetEnumerator()) {
Write-Host "Import and start system: $($system.Name)"
# Import configuration file of VM.
$vmImport = Import-AzureVM -Path $system.Value.ConfigFile
# Change VM name using current prefix.
$vmImport.RoleName = "$namePrefix-$($system.Name)"
# Change name and label of OS disk.
$vmImport.OSVirtualHardDisk.DiskName = $system.Value.OSDisk.DiskName
$vmImport.OSVirtualHardDisk.DiskLabel = $system.Value.OSDisk.Label
# Change name and label of data disks.
if ($system.Value.DataDisk1) {
$vmImport.DataVirtualHardDisks[0].DiskName = $system.Value.DataDisk1.DiskName
$vmImport.DataVirtualHardDisks[0].DiskLabel = $system.Value.DataDisk1.Label
}
if ($system.Value.DataDisk2) {
$vmImport.DataVirtualHardDisks[1].DiskName = $system.Value.DataDisk2.DiskName
$vmImport.DataVirtualHardDisks[1].DiskLabel = $system.Value.DataDisk2.Label
}
# Set corresponding subnet and create and start VM in the defined cloud service and virtual network.
# Ignore warning that the virtual network can only set the first time.
$vmImport | Set-AzureSubnet -SubnetNames $system.Value.SubnetName |
New-AzureVM –ServiceName $cloudServiceName -VNetName $vNetName -WarningAction Ignore
}
Write-Host "$(Get-Date -Format HH:mm:ss): Create VMs finished."
#endregion
#region Create RDP files for VMs.
Write-Host "$(Get-Date -Format HH:mm:ss): Create RDP files started."
# Build up path where RDP files will be stored.
$folderRdpFiles = Join-Path -Path $pathConfigFiles -ChildPath RDPs
# Create subfolder for RDP files.
New-Item -ItemType Directory -Path $folderRdpFiles -Force
# Get RDP files for all VMs in the defined cloud service.
Get-AzureVM -ServiceName $cloudServiceName |
Select-Object -Property Name, ServiceName, @{Name = "LocalPath"; Expression = {Join-Path -Path $folderRdpFiles -ChildPath "$($_.Name).rdp"} } |
Get-AzureRemoteDesktopFile
Write-Host "$(Get-Date -Format HH:mm:ss): Create RDP files finished in folder: $folderRdpFiles"
#endregion
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment