How to revert an azure disk back to its former snapshot? - azure

I have a VM in azure, and via the portal have selected its Disk, and created a snapshot of it. How do I now revert back to that snapshot for the Disk (via portal or CLI)?
I'm not looking to create new disks or VMs from the snapshot, just revert back.

How do I now revert back to that snapshot for the Disk (via portal or
CLI)?
Do you mean you want to use this snapshot to rollback your system?
Unfortunately, for now Azure does not support this, we can't use snapshot to revert back.
In Azure, we can't revert back Azure VM directly, we should create disk or VM from that snapshot.
By default, snapshot used for Azure backup. In Azure recovery services, we can restore VMs from the snapshot. Restore this VM was create a new VM with this OS disk, not rollback.

This worked for eastus zone 1 using the cloud shell in the azure portal
$SnapshotName = "my_snapshot"
$SnapshotResourceGroup = "my_resource_group"
$DiskNameOS = "my_new_snapshotdisk"
$snapshotinfo = Get-AzSnapshot -ResourceGroupName $SnapshotResourceGroup -SnapshotName $snapshotName
New-AzDisk -DiskName $DiskNameOS (New-AzDiskConfig -zone 1 -Location eastus -CreateOption Copy -SourceResourceId $snapshotinfo.Id) -ResourceGroupName $SnapshotResourceGroup
After that I went to the VM in the portal, selected "disks" and selected "swap os disk".

I did it successfully with Azure PowerShell, using Set-AzVMOSDisk. There is a module which unfortunately can only restore the snapshots that it created, but its code demonstrates how it works.
Summarised:
Get-AzSnapshot -ResourceGroupName "..." # to find the Disk ID
$vm = Get-AzVM -Name "..."
$old_disk = Get-AzDisk -Name $vm.StorageProfile.OsDisk.name
$diskconf = New-AzDiskConfig -AccountType $old_disk.sku.name -Location $old_disk.Location -SourceResourceId "Id of the disk" -CreateOption Copy
$newdisk = NewAzDisk -Disk $diskconf -ResourceGroupName "..." -DiskName "OS_disk_$((New-Guid).ToString())"
Set-AzVMOSDisk -VM $vm -ManagedDiskId $newdisk.Id -Name $newdisk.Name
Update-AzVM -ResourceGroupName "..." -VM $vm

I did it with the PS script below. It stops VM, creates a new disk using the snapshot, and then swaps VM to this new disk. Snapshot has been created on stopped VM.
$resourceGroupName = '...'
$location = 'eastus2'
$vmName = '...'
$snapshotName = '...'
$snapshotinfo = Get-AzSnapshot -ResourceGroupName $resourceGroupName -SnapshotName $snapshotName
$vm = Get-AzVM `
-ResourceGroupName $resourceGroupName `
-Name $vmName
Stop-AzVM -ResourceGroupName $resourceGroupName -Name $vm.Name -Force
# Create the new disk that you want to swap in
$newDiskName = $($vmName + "_disk_" + (Get-Date).ToString("yyyyMMddhhmm"))
$newDisk = New-AzDisk -DiskName $newDiskName (New-AzDiskConfig -zone 1 -Location $location -CreateOption Copy -SourceResourceId $snapshotinfo.Id) -ResourceGroupName $resourceGroupName
Set-AzVMOSDisk -VM $vm -ManagedDiskId $newDisk.Id -Name $newDisk.Name
Update-AzVM -ResourceGroupName $resourceGroupName -VM $vm
Start-AzVM -Name $vm.Name -ResourceGroupName $resourceGroupName

Related

Azure VM Snapshot performance issue

Can we create a snapshot when the Azure VM is in running state? By any chance does this operation will impact the VM performance
Thanks in advance
Yes, you can create a snapshot when the Azure VM is in a running state. However, it's recommended that you cleanly shut down the VM before taking a snapshot, to clear out any processes that are in progress. Refer to https://learn.microsoft.com/en-us/azure/virtual-machines/windows/snapshot-copy-managed-disk
For example, you can run the following PowerShell commands to create a snapshot.
$resourceGroupName = 'xxx'
$location = 'xxx'
$vmName = 'xxx'
$snapshotName = 'xxx'
$vm = Get-AzVM `
-ResourceGroupName $resourceGroupName `
-Name $vmName
$snapshot = New-AzSnapshotConfig `
-SourceUri $vm.StorageProfile.OsDisk.ManagedDisk.Id `
-Location $location `
-CreateOption copy
New-AzSnapshot `
-Snapshot $snapshot `
-SnapshotName $snapshotName `
-ResourceGroupName $resourceGroupName

Powershell script to create a snapshot and store it into a storage account in another location

Using powershell script, I need to create a snapshot of a VM and save the snapshot in a storage account which is in a different region. The snapshot name should also contain the date on which it was taken, so that it can be auto deleted after 30 days. Do let me know how to achieve this.
Also another major issue I am facing is how to store the snapshot in the storage account without using keys directly in the script.
This is the old script which I am using, it does not has the date in the snapshot name feature and uses storage account keys directly in the script, which is not secure.
#powershell script to create a snapshot
Select-AzSubscription -SubscriptionName 'subs name'
$subscriptionId = 'xxxxxx'
$resourceGroupName = "Rgname"
$vmName="VMname"
$Location = "East US"
#how to get-date in the name of the snap
$snapshotName = "snapname"
$vmOSDisk=(Get-AzVM -ResourceGroupName $resourceGroupName -Name $vmName).StorageProfile.OsDisk.Name
$Disk = Get-AzDisk -ResourceGroupName $resourceGroupName -DiskName $vmOSDisk
$SnapshotConfig = New-AzSnapshotConfig -SourceUri $Disk.Id -CreateOption Copy -Location $Location
$Snapshot=New-AzSnapshot -Snapshot $snapshotConfig -SnapshotName `
$snapshotName -ResourceGroupName $resourceGroupName
#powershell script to convert snapshot into managed disks
$diskName = 'ManagedDiskname'
#Provide the size of the disks in GB. It should be greater than the VHD file size.
$diskSize = '128'
$storageType = 'Premium_LRS'
Select-AzSubscription -SubscriptionId $SubscriptionId
$snapshot = Get-AzSnapshot -ResourceGroupName $resourceGroupName -SnapshotName $snapshotName
$diskConfig = New-AzDiskConfig -SkuName $storageType -Location $location -CreateOption Copy -SourceResourceId $snapshot.Id
New-AzDisk -Disk $diskConfig -ResourceGroupName $resourceGroupName -DiskName $diskName
#powershell script to save managed disk into a storage account which is in a different location
$sasExpiryDuration = "3600"
$storageAccountName = "storageacctname"
$storageContainerName = "containername"
$storageAccountKey = '(Get-AzStorageAccountKey -ResourceGroupName "Snapshot-Powershell" -AccountName "storageforsnap")'
#Provide the key of the storage account where you want to copy the VHD of the managed disk.
$storageAccountKey = 'xxxxxx'
$destinationVHDFileName = "vhdfilename"
.
$useAzCopy = 1
Select-AzSubscription -SubscriptionId $SubscriptionId
$sas = Grant-AzDiskAccess -ResourceGroupName $ResourceGroupName -DiskName $diskName -DurationInSecond $sasExpiryDuration -Access Read
$destinationContext = New-AzStorageContext -StorageAccountName $storageAccountName -StorageAccountKey $storageAccountKey
#Copy the VHD of the managed disk to the storage account
if($useAzCopy -eq 1)
{
$containerSASURI = New-AzStorageContainerSASToken -Context $destinationContext -ExpiryTime(get-date).AddSeconds($sasExpiryDuration) -FullUri -Name $storageContainerName -Permission rw
azcopy copy $sas.AccessSAS $containerSASURI
}else{
Start-AzStorageBlobCopy -AbsoluteUri $sas.AccessSAS -DestContainer $storageContainerName -DestContext $destinationContext -DestBlob $destinationVHDFileName
}
1. Azure snapshot can be auto deleted after 30 days
As far as I knew, Azure does not provide the feature. But we can implement it via a schedule task.
For example
Enable Run As account in Azure automation account
Install module Az.Automation Az.Accounts and Az.Compute in the automation account. Regarding how to install, please refer to here
Create Azure Powershell runbook with the following script in the automation ccount. For more details, please refer to here.
#get the snpshots created before 30 days
Get-AzSnapshot| Where-Object{($_.TimeCreated -lt ([datetime]::UtcNow.AddDays(-30)))}
foreach($snp in $snps){
$snp| Remove-AzSnapshot -Force
}
Create a schedule for the Azure runbook.
2. How to securely connect Azure blob
If you want to securely connect Azure blob, we can implement it with Azure AD auth. For more details, please refer to here.
For example
Assign Storage Blob Data Contributor role to user or sp
New-AzRoleAssignment -SignInName <email> `
-RoleDefinitionName "Storage Blob Data Contributor" `
-Scope "/subscriptions/<subscription>/resourceGroups/sample-resource-group/providers/Microsoft.Storage/storageAccounts/<storage-account>"
Script
Connect-AzAccount
$ResourceGroupName=""
$snapshotName=""
$sasExpiryDuration=3600
$sas =Grant-AzSnapshotAccess -SnapshotName $snapshotName -ResourceGroupName $ResourceGroupName -DurationInSecond $sasExpiryDuration -Access Read
$storageAccountName=""
$destinationContext = New-AzStorageContext -StorageAccountName $storageAccountName -UseConnectedAccount
$storageContainerName="image"
$destinationVHDFileName="test.vhd"
Start-AzStorageBlobCopy -AbsoluteUri $sas.AccessSAS -DestContainer $storageContainerName -DestContext $destinationContext -DestBlob $destinationVHDFileName
#check copy state
Get-AzStorageBlobCopyState -Container $storageContainerName -Blob $destinationVHDFileName -Context $destinationContext

How do you create Azure VM from VHD with unmanaged disk?

I have a Datacenter 2016 server with unmanaged disk. I need to be able to replicate this VM and continue using an unmanaged disk.
Do I need to provision the VM i want to replicate? Or can I just use the VHD in storage to create a new VM?
Here is my powershell script so far. Note that I tried to provision a VM
New-AzVm `
-ResourceGroupName "myResource" `
-Name "myVM" `
-ImageName "" ` //IS THIS WHERE YOU WOULD PUT A VHD?
-Location "West US 2" `
-VirtualNetworkName "my-vnet" `
-SubnetName "default" `
-SecurityGroupName "myvmNSG" `
-OpenPorts 3389, 80, 443
If you want to create an unmanaged VM from the VHD file, you can use the VM config. Here is an example using the existing NIC and VNet, you can also create the new one for it:
$NIC = Get-AzNetworkInterface -ResourceGroupName charlesUnmanaged -Name azurevm938
$VirtualMachine = New-AzVMConfig -VMName "azurevm" -VMSize "Standard_DS3"
$VirtualMachine = Add-AzVMNetworkInterface -VM $VirtualMachine -Id $NIC.Id
$VirtualMachine = Set-AzVMOSDisk -VM $VirtualMachine -Name "unmanagedos" -VhdUri $OSDiskUri -CreateOption Attach -Linux
New-AzVM -ResourceGroupName "charlesUnmanaged" -Location "East US" -VM $VirtualMachine -Verbose

Create a Azure VM with unmanaged data disks enabled using powershell

I am trying to create a azure vm using powershell so that it would allow to attach unmanaged data disks in future.
I see documentation on creating but those always create with managed disks
Example.
nic\network\etc amended
# Create storage account
$storageAccount = New-AzStorageAccount -ResourceGroupName "MyResourceGroup" -AccountName "MyStorageAccount" -Location $location -SkuName "Standard_LRS"
# Add disk
$OSDiskUri = $storageAccount.PrimaryEndpoints.Blob.ToString() + "vhds/vm-disk.vhd"
$vm = Set-AzVMOSDisk -VM $vm -Name "vm-disk" -VhdUri $OSDiskUri -CreateOption fromImage
# Create VM
New-AzVM -ResourceGroupName myResourceGroup -Location $location -VM $vm

Reducing size of Azure VM OS Disk for download/export

I would like to create an Azure VM with a smaller OS disc than the default 127gb. I've been unable to find such an option in the Azure Portal, so I have attempted to shrink the disk. I have not been successful.
I understand I can trim (using the defragmentation tool) and shrink the volume (with Disk Management) but this won't change the "physical" size of the hard disk. That is, if I shrink the disk to 40gb, there will just be 87gb unallocated and the blob will still report 127gb.
What I am attempting to achieve is to shrink the blob to match the allocated space facilitating smaller downloads/exports of the VM image (e.g. 40 vs 127gb).
Any and all help is appreciated.
I have written a blog post detailing this answer in full. But the main issue here was being able to reduce the size of the Azure VM which defaults to 127gb in order to allow for fasted export/download. The way I have achieved this is by trimming the hard drive and then using Disk2VHD to create a VHD file of the running VM. Disk2VHD will create an expandable disk that is only as large as the current data on the disc, not the entire available disk. In my case 40gb vs 127gb. If one saves this VHD file to an attached disk (read: blob storage) it can be easily downloaded via HTTP by your entire team. Thus, the download is now 40gbs instead of 127gbs. For more, please read my detailed blog post:
http://www.kevinmcloutier.com/?p=263
Original link no longer works:
https://web.archive.org/web/20161027213258/http://kevinmcloutier.com/post/4
In Azure if you create a VM it will create with some default configuration. At present it is not supported to reduce/shrink the OS disk (managed or unmanaged) size of an Azure VM from the Azure Portal (say from 128Gb to 32Gb for example), using the following process we can archive that, and cut down the disk cost.
Step 1. Open your VM and go to the Disk Management.
Step 2. Open PowerShell and execute the following command.
After successful execution you can find the following
Step 3. Now deallocate the VM from the Azure portal
Step 4. Now Go the Properties blade of the disk and copy the Resource ID
Step 5. Now execute the following PowerShell script from your local system. Must change $DiskID, $VMName, $AzSubscription with your value
# Variables
$DiskID = ""# eg. "/subscriptions/203bdbf0-69bd-1a12-a894-a826cf0a34c8/resourcegroups/rg-server1-prod-1/providers/Microsoft.Compute/disks/Server1-Server1"
$VMName = "VM-Server1"
$DiskSizeGB = 32
$AzSubscription = "Prod Subscription"
# Script
# Provide your Azure admin credentials
Connect-AzAccount
#Provide the subscription Id of the subscription where snapshot is created
Select-AzSubscription -Subscription $AzSubscription
# VM to resize disk of
$VM = Get-AzVm | ? Name -eq $VMName
#Provide the name of your resource group where snapshot is created
$resourceGroupName = $VM.ResourceGroupName
# Get Disk from ID
$Disk = Get-AzDisk | ? Id -eq $DiskID
# Get VM/Disk generation from Disk
$HyperVGen = $Disk.HyperVGeneration
# Get Disk Name from Disk
$DiskName = $Disk.Name
# Get SAS URI for the Managed disk
$SAS = Grant-AzDiskAccess -ResourceGroupName $resourceGroupName -DiskName $DiskName -Access 'Read' -DurationInSecond 600000;
#Provide the managed disk name
#$managedDiskName = "yourManagedDiskName"
#Provide Shared Access Signature (SAS) expiry duration in seconds e.g. 3600.
#$sasExpiryDuration = "3600"
#Provide storage account name where you want to copy the snapshot - the script will create a new one temporarily
$storageAccountName = "shrink" + [system.guid]::NewGuid().tostring().replace('-','').substring(1,18)
#Name of the storage container where the downloaded snapshot will be stored
$storageContainerName = $storageAccountName
#Provide the key of the storage account where you want to copy snapshot.
#$storageAccountKey = "yourStorageAccountKey"
#Provide the name of the VHD file to which snapshot will be copied.
$destinationVHDFileName = "$($VM.StorageProfile.OsDisk.Name).vhd"
#Generate the SAS for the managed disk
#$sas = Grant-AzureRmDiskAccess -ResourceGroupName $resourceGroupName -DiskName $managedDiskName -Access Read -DurationInSecond $sasExpiryDuration
#Create the context for the storage account which will be used to copy snapshot to the storage account
$StorageAccount = New-AzStorageAccount -ResourceGroupName $resourceGroupName -Name $storageAccountName -SkuName Standard_LRS -Location $VM.Location
$destinationContext = $StorageAccount.Context
$container = New-AzStorageContainer -Name $storageContainerName -Permission Off -Context $destinationContext
#Copy the snapshot to the storage account and wait for it to complete
Start-AzStorageBlobCopy -AbsoluteUri $SAS.AccessSAS -DestContainer $storageContainerName -DestBlob $destinationVHDFileName -DestContext $destinationContext
while(($state = Get-AzStorageBlobCopyState -Context $destinationContext -Blob $destinationVHDFileName -Container $storageContainerName).Status -ne "Success") { $state; Start-Sleep -Seconds 20 }
$state
# Revoke SAS token
Revoke-AzDiskAccess -ResourceGroupName $resourceGroupName -DiskName $DiskName
# Emtpy disk to get footer from
$emptydiskforfootername = "$($VM.StorageProfile.OsDisk.Name)-empty.vhd"
# Empty disk URI
#$EmptyDiskURI = $container.CloudBlobContainer.Uri.AbsoluteUri + "/" + $emptydiskforfooter
$diskConfig = New-AzDiskConfig `
-Location $VM.Location `
-CreateOption Empty `
-DiskSizeGB $DiskSizeGB `
-HyperVGeneration $HyperVGen
$dataDisk = New-AzDisk `
-ResourceGroupName $resourceGroupName `
-DiskName $emptydiskforfootername `
-Disk $diskConfig
$VM = Add-AzVMDataDisk `
-VM $VM `
-Name $emptydiskforfootername `
-CreateOption Attach `
-ManagedDiskId $dataDisk.Id `
-Lun 63
Update-AzVM -ResourceGroupName $resourceGroupName -VM $VM
$VM | Stop-AzVM -Force
# Get SAS token for the empty disk
$SAS = Grant-AzDiskAccess -ResourceGroupName $resourceGroupName -DiskName $emptydiskforfootername -Access 'Read' -DurationInSecond 600000;
# Copy the empty disk to blob storage
Start-AzStorageBlobCopy -AbsoluteUri $SAS.AccessSAS -DestContainer $storageContainerName -DestBlob $emptydiskforfootername -DestContext $destinationContext
while(($state = Get-AzStorageBlobCopyState -Context $destinationContext -Blob $emptydiskforfootername -Container $storageContainerName).Status -ne "Success") { $state; Start-Sleep -Seconds 20 }
$state
# Revoke SAS token
Revoke-AzDiskAccess -ResourceGroupName $resourceGroupName -DiskName $emptydiskforfootername
# Remove temp empty disk
Remove-AzVMDataDisk -VM $VM -DataDiskNames $emptydiskforfootername
Update-AzVM -ResourceGroupName $resourceGroupName -VM $VM
# Delete temp disk
Remove-AzDisk -ResourceGroupName $resourceGroupName -DiskName $emptydiskforfootername -Force;
# Get the blobs
$emptyDiskblob = Get-AzStorageBlob -Context $destinationContext -Container $storageContainerName -Blob $emptydiskforfootername
$osdisk = Get-AzStorageBlob -Context $destinationContext -Container $storageContainerName -Blob $destinationVHDFileName
$footer = New-Object -TypeName byte[] -ArgumentList 512
write-output "Get footer of empty disk"
$downloaded = $emptyDiskblob.ICloudBlob.DownloadRangeToByteArray($footer, 0, $emptyDiskblob.Length - 512, 512)
$osDisk.ICloudBlob.Resize($emptyDiskblob.Length)
$footerStream = New-Object -TypeName System.IO.MemoryStream -ArgumentList (,$footer)
write-output "Write footer of empty disk to OSDisk"
$osDisk.ICloudBlob.WritePages($footerStream, $emptyDiskblob.Length - 512)
Write-Output -InputObject "Removing empty disk blobs"
$emptyDiskblob | Remove-AzStorageBlob -Force
#Provide the name of the Managed Disk
$NewDiskName = "$DiskName" + "-new"
#Create the new disk with the same SKU as the current one
$accountType = $Disk.Sku.Name
# Get the new disk URI
$vhdUri = $osdisk.ICloudBlob.Uri.AbsoluteUri
# Specify the disk options
$diskConfig = New-AzDiskConfig -AccountType $accountType -Location $VM.location -DiskSizeGB $DiskSizeGB -SourceUri $vhdUri -CreateOption Import -StorageAccountId $StorageAccount.Id -HyperVGeneration $HyperVGen
#Create Managed disk
$NewManagedDisk = New-AzDisk -DiskName $NewDiskName -Disk $diskConfig -ResourceGroupName $resourceGroupName
$VM | Stop-AzVM -Force
# Set the VM configuration to point to the new disk
Set-AzVMOSDisk -VM $VM -ManagedDiskId $NewManagedDisk.Id -Name $NewManagedDisk.Name
# Update the VM with the new OS disk
Update-AzVM -ResourceGroupName $resourceGroupName -VM $VM
$VM | Start-AzVM
start-sleep 180
# Please check the VM is running before proceeding with the below tidy-up steps
# Delete old Managed Disk
Remove-AzDisk -ResourceGroupName $resourceGroupName -DiskName $DiskName -Force;
# Delete old blob storage
$osdisk | Remove-AzStorageBlob -Force
# Delete temp storage account
$StorageAccount | Remove-AzStorageAccount -Force
You would have to create your own VM image and then deploy using that. This template shows you how to deploy using your own image.
https://github.com/Azure/azure-quickstart-templates/tree/master/101-vm-from-user-image
Currently, the images in the gallery are all 127gb. Since Azure VMs only used fixed size discs, you can't just select the size.
Sapnandu's solution works. Many thanks!
I'm still not 100% sure what was the magic criteria to make it work, but finally I have a vm running with the reduced disk. Making it Gen1 definitely was one.
I tried many similar things and they all got stuck at boot time.
My way was:
Create the vm from the gallery images. You'll have a 128Gb OS disk.
Tweak the vm according to your needs. Here you can run the resize script. So, you'll end up with a ~90Gb unallocated space.
After a few failed attempts I started to value the configured vm and I really didn't want to repeat the configuration again.
Make a snapshot of this disk then make a disk from the snapshot. These options will be presented to you by the snapshot and by the disk.
Then make a new vm from the disk. Check if it boots. Boot diagnostics shows it rather quickly.
After stopping the new vm I looked up the 3 (subscriptionID,diskID,vmName) required parameters for Sapnandu's script (Step 5. in his post) and executed the script in azure cloud shell. (the icon in header)
It takes time, about 10 minutes or so.
When the script finished the new vm was running with the smaller disk.
So, there is a vm setup where the script works perfectly.

Resources