Pergunta

I want to clone the virtual disk of a running VM on Hyper-V 2012.

I know that snapshotting the VM will generate a diff disk (file extension .AVHDX). All subsequent writes are to this snapshot, and its parent is read only.

However, that parent may also be a snapshot, which means I cannot simply copy the parent.

How do I obtain a single file that contains all the virtual hard drive’s data prior to my snapshot?

Put another way, how do I export the parent of the current snapshot to a single .VHDX file?

Ideally, I would like to know how to do this using the Hyper-V V2 WMI API.

Foi útil?

Solução

Hyper-V 2012 and later supports live merge of snapshots but not export of a running VM.
Hyper-V 2012 R2 supports live export. So, upgrade and move on, nothing to see here.

However...

If you take a snapshot of a VM, you can then add a differencing disk to the parent disk of the snapshot, create a VM from that, export that VM, then destroy the VM, then destroy the differencing disk.

It seems very round-about, but this is the only way that I know of "cloning" a running Hyper-V VM (as it is the VHD that becomes the issue, the settings can be copied and a new VM created, those settings don't need to be 'cloned').

If your VM does not have any snapshots, then you need to create one to make this work. You will be 'cloning' the snapshot while the running VM state is allowed to write back to the AVHDX known as 'now'.

Since this copy that is being created is never powered on, CPU and RAM does not matter.

Because this is not a snapshot, with the export Hyper-V gives you the differencing disk plus the parent.
If you exported a snapshot you get a single virtual disk, since Hyper-V does special things with AVHDX files.
If you want a single file, then you merge the diff that is in the export. The merge ends up breaking the configuration of the exported VM, since the differencing disk is deleted so you have to rename it.
But again, we are doing this to get a copy of the disk in a very clean (and proper) way.

Yes, a lot of work for a running export. And to avoid any file locking issues with virtual disks.

No time for complete code, but I walked this through the PowerShell just to verify it is possible.

$snap = Get-VMSnapshot "datest"

PS C:\Windows\system32> $snap.HardDrives

VMName ControllerType ControllerNumber ControllerLocation DiskNumber Path                     
------ -------------- ---------------- ------------------ ---------- ----                     
DATest IDE            0                0                             D:\DATest\Server2012.vhdx


PS C:\Windows\system32> New-VHD -Differencing -ParentPath $snap.HardDrives[0].Path -Path D:\test\test.vhdx


ComputerName            : SWEETUMS
Path                    : D:\test\test.vhdx
VhdFormat               : VHDX
VhdType                 : Differencing
FileSize                : 4194304
Size                    : 42949672960
MinimumSize             : 42948624384
LogicalSectorSize       : 512
PhysicalSectorSize      : 4096
BlockSize               : 2097152
ParentPath              : D:\DATest\Server2012.vhdx
FragmentationPercentage : 
Alignment               : 1
Attached                : False
DiskNumber              : 
IsDeleted               : False
Number                  : 


PS C:\Windows\system32> New-VM -Name Test -Path D:\Test -VHDPath D:\test\test.vhdx 

Name State CPUUsage(%) MemoryAssigned(M) Uptime   Status            
---- ----- ----------- ----------------- ------   ------            
Test Off   0           0                 00:00:00 Operating normally


Export-vm -Name Test -Path d:\newTest -Passthru

# Get the FullName of the parent disk for renaming later

Merge-VHD 'D:\NewTest\Test\Virtual Hard Disks\test.vhdx' -Force

Rename-Item 'D:\NewTest\Test\Virtual Hard Disks\Server2012.vhdx' 'D:\NewTest\Test\Virtual Hard Disks\test.vhdx'

I have to blog all of this now..

Outras dicas

Using Windows 2012 R2?

You can export directly using the ExportSystemDefinition method of the Msvm_VirtualSystemManagementService class

PowerShell example from Taylor Brown:

# Obtain Msvm_ComputerSystem object corresponding to VM to export
$vmName = "MyVirtualMachine"
$Msvm_ComputerSystem = Get-WmiObject -Namespace root\virtualization\v2 -Class Msvm_ComputerSystem -Filter "ElementName='$vmName'"

# Edit copy of the Msvm_VirtualSystemExportSettingData associated with your VM
$Msvm_VirtualSystemExportSettingData = $Msvm_ComputerSystem.GetRelated("Msvm_VirtualSystemExportSettingData","Msvm_SystemExportSettingData",$null,$null, $null, $null, $false, $null)
$Msvm_VirtualSystemExportSettingData.CopySnapshotConfiguration = 0 # 0=ExportAllSnapshots, 1=ExportNoSnapshots, 2=ExportOneSnapshot

# Call ExportSystemDefinition method of Msvm_VirtualSystemManagementService singleton
$Msvm_VirtualSystemManagementService = Get-WmiObject -Namespace root\virtualization\v2 -Class Msvm_VirtualSystemManagementService
$Msvm_VirtualSystemManagementService.ExportSystemDefinition($Msvm_ComputerSystem, "c:\export_folder", $Msvm_VirtualSystemExportSettingData.GetText(1))
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top