Last active
August 29, 2015 14:14
-
-
Save pkirch/695eb59a532265a5dd55 to your computer and use it in GitHub Desktop.
Script for IT Camp Hybrid IT.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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