Freigeben über


Hyper-V WMI: Creating/Applying/Deleting Virtual Machine Snapshots

After I finished writting this I relized it got a bit long... - I guess I had a lot to talk about!  Hope you enjoy it (or at least find it mildly useful)

imageHyper-V implements a feature known as snapshots, this should not be confused with a SAN snapshot or a VSS snapshot these snapshots are quite different.  A Hyper-V snapshot allows you to save off the current state of a virtual machine even while the virtual machine is running or paused.  You can then you can revert back to this state at a latter point…  You can create tree’s of snapshots (see screen shot), think about application testing when you might need an XP RTM image, XP SP1, XP SP2, XP SP1 that was upgraded to SP2 and then rolled back to SP1 etc…  With a snapshot tree you can create all of these interesting combinations without having to reinstall a physical or virtual machine 20 times… and when the next service pack comes out you can just apply the interesting base snapshots create a new snapshot and install the service pack – Major Time Saver!

The way a snapshot works is that Hyper-V creates a copy of the virtual machine configuration (network connections, disk configuration, cpu count, ram count etc…) Hyper-V then creates a special diffrencing VHD file known as an AVHD for every virtual hard disk connected to the VM to prevent the current VHD from being changed.  If the virtual machine is running a full copy of the guest memory is also saved – unlike a saved state the virtual machine continues to run while this is occurring.  There are a few things that should be noted, since Hyper-V effectively uses a diffrencing VHD to branch the hard disk state VM’s that are using passthough disks or cd’s can not be snapshoted.  Along the same lines just like diffrencing VHD files have a disk read and write performance penalty over a fixed or even dynamically expanding VHD snapshots to incur this cost.  Another thing to note is that the AVHD file and saved memory file by default is located in the same location as the virtual machine configuration, this can be changed either by creating the virtual machine in a non-default location or more comely in the Virtual Machine Settings’s UI under Management (Snapshot File Location).

Snapshot’s are excellent for test and development they are a huge time saver.  They are also great for staging up a server you get the ability to undo when you accidentally type the wrong machine name or password… Just remember to merge your snapshots before putting the server into production, to merge a snapshot you just deleted the snapshot tree with the virtual machine off, it will then start a background merge which you can monitor from the Hyper-V management UI.  When the merge is completed you will have a flat VHD that you can then put into production with no-performance impact.  Now let’s see some code!

Taking a Snapshot
$VMManagementService = Get-WmiObject -Namespace root\virtualization -Class Msvm_VirtualSystemManagementService $SourceVm = Get-WmiObject -Namespace root\virtualization -Query "Select * From Msvm_ComputerSystem Where ElementName='VmToSnapshot'" $result = $VMManagementService.CreateVirtualSystemSnapshot($SourceVm) #ProcessWMIJob($result)
Applying a Snapshot
$VMManagementService = Get-WmiObject -Namespace root\virtualization -Class Msvm_VirtualSystemManagementService $SourceVm = Get-WmiObject -Namespace root\virtualization -Query "Select * From Msvm_ComputerSystem Where ElementName= 'VmToSnapshot' " $Snapshot = Get-WmiObject -Namespace root\virtualization -Query "Associators Of {$SourceVm} Where AssocClass=Msvm_ElementSettingData ResultClass=Msvm_VirtualSystemSettingData" $result = $VMManagementService.ApplyVirtualSystemSnapshot($SourceVm, $Snapshot) #ProcessWMIJob($result)
Deleting a Snapshot
$VMManagementService = Get-WmiObject -Namespace root\virtualization -Class Msvm_VirtualSystemManagementService $SourceVm = Get-WmiObject -Namespace root\virtualization -Query "Select * From Msvm_ComputerSystem Where ElementName='VmToSnapshot'" $Snapshot = Get-WmiObject -Namespace root\virtualization -Query "Associators Of {$SourceVm} Where AssocClass=Msvm_ElementSettingData ResultClass=Msvm_VirtualSystemSettingData" $result = $VMManagementService.RemoveVirtualSystemSnapshot($Snapshot) #ProcessWMIJob($result)
Enumerating Snapshots
$SourceVm = Get-WmiObject -Namespace root\virtualization -Query "Select * From Msvm_ComputerSystem Where ElementName='VmToSnapshot'" Get-WmiObject -Namespace root\virtualization -Query "Associators Of {$SourceVm} Where AssocClass=Msvm_ElementSettingData ResultClass=Msvm_VirtualSystemSettingData" | Format-List -Property ElementName, InstanceID
Enumerating Snapshots – With a bit more information…
$SourceVm = Get-WmiObject -Namespace root\virtualization -Query "Select * From Msvm_ComputerSystem Where ElementName='VmToSnapshot'" $Snapshots = Get-WmiObject -Namespace root\virtualization -Query "Associators Of {$SourceVm} Where AssocClass=Msvm_ElementSettingData ResultClass=Msvm_VirtualSystemSettingData" $script:list = @() foreach ($Snapshot in $Snapshots) {     $SnapObj = New-Object -TypeName System.Object     $SnapObj | Add-Member -MemberType NoteProperty -Name SnapshotName -Value $Snapshot.ElementName     $SnapObj | Add-Member -MemberType NoteProperty -Name SnapshotID -Value $Snapshot.InstanceID     $SnapObj | Add-Member -MemberType NoteProperty -Name SnapshotParentName -Value ([WMI]$Snapshot.Parent).ElementName     $script:list += $SnapObj } $script:list
ProcessWMIJob Function

Put this block at the top of your script and uncomment the ProcessWMIJob call if you want the function call to wait for completion and provide error messages…

function ProcessWMIJob {     param ( [System.Management.ManagementBaseObject]$Result )     if ($Result.ReturnValue -eq 4096) {         $Job = [WMI]$Result.Job         while ($Job.JobState -eq 4) {             Write-Progress $Job.Caption "% Complete" -PercentComplete $Job.PercentComplete             Start-Sleep -seconds 1             $Job.PSBase.Get() }         if ($Job.JobState -ne 7) {             Write-Error $Job.ErrorDescription             Throw $Job.ErrorDescription }         Write-Progress $Job.Caption "Completed" -Completed $TRUE }     elseif ($Result.ReturnValue -ne 0) {         Write-Error "Hyper-V WMI Job Failed!"         Throw $Result.ReturnValue } } 

ENJOY!

Taylor Brown
Hyper-V Integration Test Lead
https://blogs.msdn.com/taylorb

clip_image001

Comments

  • Anonymous
    June 16, 2008
    PingBack from http://blog.a-foton.ru/2008/06/17/hyper-v-wmi-creatingapplyingdeleting-virtual-machine-snapshots/

  • Anonymous
    June 17, 2008
    Hi, In the ProcessWMIJob function, when $Result.ReturnValue is not 0 or 4096, you throw. How can we map $Result.ReturnValue to a meaningful description of the error (other than just "job failed") ? thanks, Marc

  • Anonymous
    June 17, 2008
    Marc, I am working on a post for latter this week to talk about this problem - and hopefully a good solution to it... A stop gap is to look at the windowsvirtualzation.mof file in system32... -Taylor

  • Anonymous
    June 18, 2008
    Marc, See my new post - http://blogs.msdn.com/taylorb/archive/2008/06/18/hyper-v-wmi-rich-error-messages-for-non-zero-returnvalue-no-more-32773-32768-32700.aspx -taylor

  • Anonymous
    June 29, 2008
    James O'Neill: I've decided to go ahead and post the PowerShell library I have been working on

  • Anonymous
    June 29, 2008
    Hyper-V implements a feature known as snapshots, this should not be confused with a SAN snapshot or a

  • Anonymous
    July 09, 2008
    James O'Neill: I've decided to go ahead and post the PowerShell library I have been working on

  • Anonymous
    July 28, 2008
    Today, I ventured into the IT Pro field and trying to figure out how to write my first PowerShell implementation

  • Anonymous
    August 12, 2008
    I don't suppose you could post the VBScript version of these since power shell does not run on server core. Thanks,

  • Anonymous
    October 02, 2008
    I had a question, I have only one VM (not running) and when I use the query: "Select * from Msvm_ComputerSystem", it gives back the result set containing details of only the host computer system and NOT the virtual machine present. Any idea why this is happening?

  • Anonymous
    March 02, 2009
    Hi Your post was useful. But, i face problem in low disk space. Since, deletion of snapshot doesnt delete the differencing disks(.avhd) and they are not merged due to active running of VM. Is there a way to script turn off and after merge completes turn on the VM on deletion of snapshot?  ==================================
    New Post Just For You Today!

  • Anonymous
    May 30, 2010
    hi, I want to stop VM integration services "Time synchronization", how to do it by hyper-v WMI programe Thanks

  • Anonymous
    February 23, 2011
    what an owesome job with those scripts. could you please tell me what changes do I need to make to allow the script that deletes snapshots, to delete all snapshots of a specific VM or something like Delete Snapshot subtree? I'd really appreciate your help with this.

  • Anonymous
    June 10, 2011
    Taking a snapshot example above terminates in Powershell with an error "cannot call a method on a null value expression" What am i missing?

  • Anonymous
    December 09, 2013
    I do not understand where and how to run these scripts. Can you please describe how to use these scripts? Thanks.

  • Anonymous
    March 17, 2014
    i need code for creating vm using wmi in c#