Loading

Restore Azure ARM Virtual Machine with Special Configuration

Below is a handy script for restoring a VM with Special Configuration

Please Note: this will only work where the VM still exists in the Azure. this process would be used to recover the VM from a previous day or if became corrupt. If the VM completely disappeared then additional steps will be required to manually recreate Availability Sets and NICs.

This script focus on restore NIC, ILB, Availability Sets , OMS, Diagnostic Settings and Antimalware


# Login to Azure PowerShell
Login-AzureRmAccount
$YourSubscriptionName= ''
Get-AzureRmSubscription –SubscriptionName $YourSubscriptionName | Select-AzureRmSubscription
Get-AzureSubscription –SubscriptionName $YourSubscriptionName | Select-AzureRmSubscription
Get-AzureRmContext

#Set the restore date
$startDate = Get-Date -Date '21 December 2016 00:00:00'
$endDate = Get-Date -Date '21 December 2016 23:59:59'

#Global Settings
$loc = 'North Europe'
$rgname = ''
$VMName = ''
$RestoreVMName = $VMName #Only Change if you want to give the VM a New Name (for Testing)
$VaultName = ''
$StorageAccount = ''
$workspaceName = "" #The OMS Name

#XML Download name and location
$diagnosticsconfig_path = 'DiagnosticsPubConfig.xml'
$VMNameConfig_path = 'VMConfig.json'
$RestoreVMNameConfig_path = 'RestoreVMConfig.json'

#Backup Diagnostic Settings
$publicsettings = (Get-AzureRmVMDiagnosticsExtension -ResourceGroupName $rgname -VMName $vmname).PublicSettings
$encodedconfig = (ConvertFrom-Json -InputObject $publicsettings).xmlCfg
$xmlconfig = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($encodedconfig))
$xmlconfig | Export-Clixml -Path $diagnosticsconfig_path

#Backup VM Settings
$VmObject = Get-AzureRmVM -ResourceGroupName $rgname -Name $Vmname
ConvertTo-Json -InputObject $VmObject | Out-File -FilePath $VMNameConfig_path
$destination_path = $VMNameConfig_path
$oldconfobj = ((Get-Content -Path $destination_path -Encoding Unicode)).TrimEnd([char]0x00) | ConvertFrom-Json

#Remember to remove the remark to remove the VM
#Remove-AzureRmVM -ResourceGroupName $rgname -Name $VMName

$vault = Get-AzureRmRecoveryServicesVault -Name $VaultName -ResourceGroupName $rgname
Set-AzureRmRecoveryServicesVaultContext -Vault $vault

$namedContainer = Get-AzureRmRecoveryServicesBackupContainer -ContainerType AzureVM –Status Registered -FriendlyName $RestoreVMName
$backupitem = Get-AzureRmRecoveryServicesBackupItem –Container $namedContainer –WorkloadType "AzureVM"

#Select the backup Set
$rp = Get-AzureRmRecoveryServicesBackupRecoveryPoint -Item $backupitem -StartDate $startdate.ToUniversalTime() -EndDate $enddate.ToUniversalTime()
$rp[0]

#Start the Restore Process
$restorejob = Restore-AzureRmRecoveryServicesBackupItem -RecoveryPoint $rp[0] -StorageAccountName $StorageAccount -StorageAccountResourceGroupName $rgname
$restorejob

#Wait for Restore to complete
$restorejob = Get-AzureRmRecoveryServicesBackupJob -Job $restorejob
$details = Get-AzureRmRecoveryServicesBackupJobDetails -Job $restorejob

#Get Details from Backup Configuration Properties

$properties = $details.properties
$storageAccountName = $properties["Target Storage Account Name"]
$containerName = $properties["Config Blob Container Name"]
$blobName = $properties["Config Blob Name"]

Set-AzureRmCurrentStorageAccount -Name $storageaccountname -ResourceGroupName $rgname
$Restoredestination_path = $RestoreVMNameConfig_path
Get-AzureStorageBlobContent -Container $containerName -Blob $blobName -Destination $Restoredestination_path
$obj = ((Get-Content -Path $Restoredestination_path -Encoding Unicode)).TrimEnd([char]0x00) | ConvertFrom-Json
$vm = New-AzureRmVMConfig -VMSize $obj.HardwareProfile.VirtualMachineSize -VMName $VMName -AvailabilitySetId $oldconfobj.AvailabilitySetReference.id #$AvailabilitySet.Id

Set-AzureRmVMOSDisk -VM $vm -Name "osdisk" -VhdUri $obj.StorageProfile.OSDisk.VirtualHardDisk.Uri -CreateOption “Attach”
$vm.StorageProfile.OsDisk.OsType = $obj.StorageProfile.OSDisk.OperatingSystemType foreach($dd in $obj.StorageProfile.DataDisks)
{
$vm = Add-AzureRmVMDataDisk -VM $vm -Name "datadisk1" -VhdUri $dd.VirtualHardDisk.Uri -DiskSizeInGB 127 -Lun $dd.Lun -CreateOption Attach
}

#Connect existing NIC
$vm=Add-AzureRmVMNetworkInterface -VM $vm -Id $oldconfobj.NetworkInterfaceIDs[0]

#CreateVM
$vm.StorageProfile.OsDisk.OsType = $obj.StorageProfile.OSDisk.OperatingSystemType
New-AzureRmVM -ResourceGroupName $rgname -Location $loc -VM $vm

#Attach Antimalware Extension
$RegularServer = @'
{
"AntimalwareEnabled": true,
"RealtimeProtectionEnabled": true,
"ScheduledScanSettings": {
"isEnabled": false,
"day": 1,
"time": 10,
"scanType": "Full"
},
"Exclusions": {
"Extensions": ".MDF;.LDF;.NDF",
"Paths": "%systemroot%:\\inetpub\\temp\\IIS",
"Processes": ""
}
}
'@
$TypeHandlerVersion = ((Get-AzureRmVMExtensionImage -Location 'North Europe' -PublisherName 'Microsoft.Azure.Security' -Type 'IaaSAntimalware').Version[-1][0..2] -join '')
Set-AzureRmVMExtension -ResourceGroupName $rgname -VMName $vmname -Name 'IaaSAntimalware' -Publisher 'Microsoft.Azure.Security' -ExtensionType 'IaaSAntimalware' -SettingString $RegularServer -Location $loc -TypeHandlerVersion $TypeHandlerVersion

#Enable Diagnostic Logging
Set-AzureRmVMDiagnosticsExtension -ResourceGroupName $rgname -VMName $vmname -DiagnosticsConfigurationPath $diagnosticsconfig_path

#Attach OMS Resource
$workspace = (Get-AzureRmOperationalInsightsWorkspace).Where({$_.Name -eq $workspaceName})
if ($workspace.Name -ne $workspaceName)
{
Write-Error "Unable to find OMS Workspace $workspaceName. Do you need to run Select-AzureRMSubscription?"
}
$workspaceId = $workspace.CustomerId
$workspaceKey = (Get-AzureRmOperationalInsightsWorkspaceSharedKeys -ResourceGroupName $workspace.ReourceGroupName -Name $workspace.Name).PrimarySharedKey
Set-AzureRmVMExtension -ResourceGroupName $rgname -VMName $VMName -Name 'MicrosoftMonitoringAgent' -Publisher 'Microsoft.EnterpriseCloud.Monitoring' -ExtensionType 'MicrosoftMonitoringAgent' -TypeHandlerVersion '1.0' -Location $loc -SettingString "{'workspaceId': '$workspaceId'}" -ProtectedSettingString "{'workspaceKey': '$workspaceKey'}"