Monday, June 23, 2008

Exporting and Importing virtual machines

Exporting virtual machine

Unlike VS 2005, when you want to move a virtual machine from one host to another, you cannot simply copy the configuration file (.VMC) and the VHD file and "make it "appear on the destination host with Hyper-V. To perform the same operation, you need to export the VM from the source host system, copy all the export files to the destination host and then import it into Hyper-V.

When exporting a VM, you can either export only configuration files (that contains all settings for this VM) or include all save state files (.vsv files), snapshot files (.AVHD files) and VM binary (.VHD file).

After you specify a root folder to store export files, the export operation will create a folder structure for you under the root folder as follow: ( assuming that the root folder is called C:\Export)

C:\Export

|----------

| ---------------- Virtual Machines

| ---------------- Virtual Hard Disks

The Virtual Machines sub-folder contains an export file (.EXP) that Hyper-V creates for export and eventually VSV files and AVHD files if you specify the option to export save state files for export. The EXP file will be read by the import operation to re-create settings for virtual machine at destination.

The Virtual Hard Disks sub-folder is the location where VHD file will reside.

To script the export operation with Hyper-V WMI, you simply call the method of the Msvm_VirtualSystemManagementService Class and specify a reference to the VM to be exported, a flag that indicates whether you want to export system state files or not and an export folder. The call returns either 0 or 4096. All other values indicate an error in the parameters passed to the call.
If it returns 0, it means that the method is executed synchronously, If it returns 4096, the method is executed asynchronously and the Job output parameter can be used to track progress of the operation.

Here is an example:

## Get reference to a VM to be exported
PS C:\> $Core = get-wmiobject -namespace root\virtualization -class Msvm_ComputerSystem -filter " ElementName = 'IIS-CORE' "

## Connect to the Virtual machine Management Service
PS C:\> $VM_Service = get-wmiobject –namespace root\virtualization –class Msvm_VirtualSystemManagementService

## call the Export method
PS C:\> $status = $VM_Service.ExportVirtualSystem($Core.__PATH, $True, "C:\Export")
PS C:\> If ($Status.ReturnValue -eq 0) { write-host "Operation Sucessful"; exit}
PS C:\> if ( $status.ReturnValue -eq 4096) { $JobStatus = $Status.Job.JobState; while ($JobStatus -ne 0) { sleep(1) } }

Importing virtual machines

The next step is to copy the folder structure under C:\Export to the destination host. It is not recommended to import a VM directly from the export folder and the import operation does not support network drive or network share folder so you can't simply point the import operation to a network share like \\Server\C$\Export.

Here is an example of scripting the import operation:

## Connect to the Virtual machine Management Service
PS C:\> $VM_Service = get-wmiobject –namespace root\virtualization –class Msvm_VirtualSystemManagementService

## call the Import method
PS C:\> $FlagGenerateNewID = $True # To ensure that the new imported VM will always get a new ID (GUID)
PS C:\> $status = $VM_Service.ImportVirtualSystem("C:\VMs\IIS-CORE", $FlagGenerateNewID)
PS C:\> If ($Status.ReturnValue -eq 0) { write-host "Operation Sucessful"; exit}
PS C:\> if ( $status.ReturnValue -eq 4096) { $JobStatus = $Status.Job.JobState; while ($JobStatus -ne 0) { sleep(1) } }

Bulk Export and Import

If you have a set of virtual machines to be exported from one machine and then to be imported on a different host, you can automate the operation as follow:

On the Source Server

$VM_Service = get-wmiobject -computer $SourceServer –namespace root\virtualization –class Msvm_VirtualSystemManagementService

$ListofVMs = get-wmiobject -computer $SourceServer -namespace root\virtualization -class Msvm_ComputerSystem -filter " ElementName <>Name"

foreach ($VM in $ListofVMs)
{

$status = $VM_Service.ExportVirtualSystem($VM.__PATH, $True, "C:\Export")
If ($Status.ReturnValue -eq 0) { write-host "Operation Sucessful"; exit}
if ( $status.ReturnValue -eq 4096) { $JobStatus = $Status.Job.JobState; while ($JobStatus -ne 0) { sleep(1) } }

}

robocopy /z /s C:\Export \\$DestServer\C$\VMs

On the Destination Server

$VM_Service = get-wmiobject -computer $DestServer –namespace root\virtualization –class Msvm_VirtualSystemManagementService

$ListOfFolders = dir "C:\VMs" | where { $_.PSIsContainer} | select FullName
foreach ($f in $ListOfFolders)
{
$Folder = $f.FullName
$Status = $VM_Service.ImportVirtualSystem($Folder,$True)
If ($Status.ReturnValue -eq 0) { write-host "Operation Sucessful"; exit}
if ( $status.ReturnValue -eq 4096) { $JobStatus = $Status.Job.JobState; while ($JobStatus -ne 0) { sleep(1) } }

}

No comments: