// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) Microsoft. All rights reserved.
namespace Microsoft.Samples.HyperV.Migration
{
using System;
using System.IO;
using System.Management;
using System.Diagnostics;
using System.Globalization;
using Microsoft.Samples.HyperV.Common;
class VmMigration : MigrationCommon
{
///
/// Migrates a VM without any modification, using all defaults.
///
/// Migration source host name.
///
/// Migration destination host name.
///
/// VM name.
public
void
VmMigrationSimple(
string sourceHost,
string destinationHost,
string vmName
)
{
ManagementScope srcScope = new ManagementScope(
@"\\" + sourceHost + @"\root\virtualization\v2", null);
using (ManagementObject migrationSettingData = GetMigrationSettingData(srcScope))
{
migrationSettingData["MigrationType"] = MigrationType.VirtualSystem;
migrationSettingData["TransportType"] = TransportType.TCP;
// Perform migration.
Console.WriteLine("Performing migration...");
Migrate(srcScope,
vmName,
destinationHost,
migrationSettingData.GetText(TextFormat.CimDtd20),
null,
null);
}
}
///
/// Migrates a VM using compression.
///
/// Migration source host name.
/// Migration destination host name.
/// VM name.
public
void
VmMigrationWithCompression(
string sourceHost,
string destinationHost,
string vmName
)
{
ManagementScope srcScope = new ManagementScope(
@"\\" + sourceHost + @"\root\virtualization\v2", null);
using (ManagementObject migrationSettingData = GetMigrationSettingData(srcScope))
{
migrationSettingData["MigrationType"] = MigrationType.VirtualSystem;
migrationSettingData["TransportType"] = TransportType.TCP;
migrationSettingData["EnableCompression"] = true;
// Perform migration.
Console.WriteLine("Performing migration...");
Migrate(srcScope,
vmName,
destinationHost,
migrationSettingData.GetText(TextFormat.CimDtd20),
null,
null);
}
}
///
/// Migrates a VM using SMB.
///
/// Migration source host name.
/// Migration destination host name.
/// VM name.
public
void
VmMigrationOverSmb(
string sourceHost,
string destinationHost,
string vmName
)
{
ManagementScope srcScope = new ManagementScope(
@"\\" + sourceHost + @"\root\virtualization\v2", null);
using (ManagementObject migrationSettingData = GetMigrationSettingData(srcScope))
{
migrationSettingData["MigrationType"] = MigrationType.VirtualSystem;
migrationSettingData["TransportType"] = TransportType.SMB;
// Perform migration.
Console.WriteLine("Performing migration...");
Migrate(srcScope,
vmName,
destinationHost,
migrationSettingData.GetText(TextFormat.CimDtd20),
null,
null);
}
}
///
/// Check migratability of a VM without any modification, using all defaults.
///
/// Migration source host name.
///
/// Migration destination host name.
///
/// VM name.
public
void
VmMigrationSimpleCheck(
string sourceHost,
string destinationHost,
string vmName
)
{
ManagementScope srcScope = new ManagementScope(
@"\\" + sourceHost + @"\root\virtualization\v2", null);
using (ManagementObject migrationSettingData = GetMigrationSettingData(srcScope))
{
migrationSettingData["MigrationType"] = MigrationType.VirtualSystem;
migrationSettingData["TransportType"] = TransportType.TCP;
// Perform migration check.
Console.WriteLine("Performing migratability check...");
CheckMigratability(srcScope,
vmName,
destinationHost,
migrationSettingData.GetText(TextFormat.CimDtd20),
null,
null);
}
}
///
/// Migrates a VM without any modification, using all defaults and
/// provide destination host IP addresses on which to perform
/// migration.
///
/// Migration source host name.
///
/// Migration destination host name.
///
/// VM name.
public
void
VmMigrationSimpleWithIpList(
string sourceHost,
string destinationHost,
string vmName
)
{
ManagementScope srcScope = new ManagementScope(
@"\\" + sourceHost + @"\root\virtualization\v2", null);
using (ManagementObject migrationSettingData = GetMigrationSettingData(srcScope))
{
migrationSettingData["MigrationType"] = MigrationType.VirtualSystem;
migrationSettingData["TransportType"] = TransportType.TCP;
// Set IP address list.
migrationSettingData["DestinationIPAddressList"] =
GetMigrationDestinationListenAddresses(destinationHost);
// Perform migration.
Console.WriteLine("Performing migration...");
Migrate(srcScope,
vmName,
destinationHost,
migrationSettingData.GetText(TextFormat.CimDtd20),
null,
null);
}
}
///
/// Migrates a VM to a new data root.
///
/// Migration source host name.
///
/// Migration destination host name.
///
/// VM name.
public
void
VmMigrationSimpleWithNewDataRoot(
string sourceHost,
string destinationHost,
string vmName
)
{
string newDataRoot = "C:\\NewDataRoot";
ManagementScope srcScope = new ManagementScope(
@"\\" + sourceHost + @"\root\virtualization\v2", null);
using (ManagementObject migrationSettingData = GetMigrationSettingData(srcScope))
using (ManagementObject vm = WmiUtilities.GetVirtualMachine(vmName, srcScope))
using (ManagementObject vssd = WmiUtilities.GetVirtualMachineSettings(vm))
{
migrationSettingData["MigrationType"] = MigrationType.VirtualSystem;
migrationSettingData["TransportType"] = TransportType.TCP;
vssd["ConfigurationDataRoot"] = newDataRoot;
// Perform migration.
Console.WriteLine("Performing migration...");
Migrate(srcScope,
vmName,
destinationHost,
migrationSettingData.GetText(TextFormat.CimDtd20),
vssd.GetText(TextFormat.CimDtd20),
null);
}
}
///
/// Migrate a planned VM, perform fixup, migrate running state to
/// planned VM.
///
/// Migration source host name.
///
/// Migration destination host name.
///
/// VM name.
public
void
VmMigrationDetailed(
string sourceHost,
string destinationHost,
string vmName
)
{
ManagementScope srcScope = new ManagementScope(
@"\\" + sourceHost + @"\root\virtualization\v2", null);
using (ManagementObject migrationSettingData = GetMigrationSettingData(srcScope))
using (ManagementObject vm = WmiUtilities.GetVirtualMachine(vmName, srcScope))
{
//
// Step - 1: Create a planned VM at destination with the
// VM configuration.
//
migrationSettingData["MigrationType"] = MigrationType.VirtualSystem;
migrationSettingData["TransportType"] = TransportType.TCP;
migrationSettingData["DestinationIPAddressList"] =
GetMigrationDestinationListenAddresses(destinationHost);
Console.WriteLine("Creating planned VM at destination...");
migrationSettingData["MigrationType"] = MigrationType.Staged;
Migrate(srcScope,
vmName,
destinationHost,
migrationSettingData.GetText(TextFormat.CimDtd20),
null,
null);
//
// Step - 2: Check migratability. If the VM cannot be migrated to
// the created planned VM, then check the reasons and fix the
// created planned VM accordingly.
//
migrationSettingData["MigrationType"] = MigrationType.VirtualSystem;
migrationSettingData["DestinationPlannedVirtualSystemId"] = vm["Name"];
Console.WriteLine(
"Check VM migratability to the created Planned VM...");
while (!CheckMigratability(srcScope,
vmName,
destinationHost,
migrationSettingData.GetText(TextFormat.CimDtd20),
null,
null))
{
Console.WriteLine("The VM is not migratable to the planned VM. " +
"Please fix the planned VM.");
//
// To fix up the planned VM created at migration destination, see
// the documentation and samples for planned VM.
// Keep performing step-2 until it succeeds without any error.
//
Console.WriteLine("Please press ENTER after fixing the planned VM");
Console.ReadLine();
}
//
// Step - 3: After CheckMigratability succeeds, perform the
// migration, using the same migration parameters as the check.
//
Console.WriteLine("Migrating VM to the created Planned VM...");
Migrate(srcScope,
vmName,
destinationHost,
migrationSettingData.GetText(TextFormat.CimDtd20),
null,
null);
}
}
///
/// Performs compatibility check for the VM or for the two host
/// computer systems.
///
/// Source host computer system.
/// Destination host computer system.
/// Optional, the virtual machine name.
public
void
CheckCompatibility(
string sourceHost,
string destinationHost,
string systemName = null
)
{
if (systemName == null)
{
systemName = sourceHost;
}
ManagementScope sourceScope = new ManagementScope(
@"\\" + sourceHost + @"\root\virtualization\v2", null);
object compatibilityInfo = null;
// Get compatibility information for the source host.
using (ManagementObject computerSystem = WmiUtilities.GetVirtualMachine(systemName, sourceScope))
using (ManagementObject sourceService = GetVirtualMachineMigrationService(sourceScope))
using (ManagementBaseObject sourceInParams =
sourceService.GetMethodParameters("GetSystemCompatibilityInfo"))
{
sourceInParams["ComputerSystem"] = computerSystem.Path.Path;
using (ManagementBaseObject sourceOutParams =
sourceService.InvokeMethod("GetSystemCompatibilityInfo", sourceInParams, null))
{
WmiUtilities.ValidateOutput(sourceOutParams, sourceScope);
compatibilityInfo = sourceOutParams["CompatibilityInfo"];
}
}
//
// Pass the compatibility blob to the destination host and check
// for compatibility.
//
ManagementScope destinationScope = new ManagementScope(
@"\\" + destinationHost + @"\root\virtualization\v2", null);
// Get compatibility information for the source host.
using (ManagementObject destinationService = GetVirtualMachineMigrationService(destinationScope))
using (ManagementBaseObject destinationInParams =
destinationService.GetMethodParameters("CheckSystemCompatibilityInfo"))
{
destinationInParams["CompatibilityInfo"] = compatibilityInfo;
using (ManagementBaseObject destinationOutParams =
destinationService.InvokeMethod("CheckSystemCompatibilityInfo", destinationInParams, null))
{
uint returnValue = (uint)destinationOutParams["ReturnValue"];
if (returnValue == 0)
{
Console.WriteLine("The VM or the systems are compatible");
}
else if (returnValue == 32784)
{
Console.WriteLine("The VM or the systems are not compatible");
}
else
{
throw new ManagementException("The method call failed.");
}
}
}
}
///
/// Gets offline compatibility vectors for the VM and host computer systems and compares them.
///
/// Host computer system name.
/// VM computer system name.
public
void
CompareCompatibilityVectors(
string hostName,
string vmName
)
{
bool isCompatible = false;
object vmCompatibilityVectors = null;
object hostCompatibilityVectors = null;
ManagementScope sourceScope = new ManagementScope(
@"\\" + hostName + @"\root\virtualization\v2", null);
using (ManagementObject sourceService = GetVirtualMachineMigrationService(sourceScope))
{
//
//Get VM compatibility vectors.
//
using (ManagementObject vm = WmiUtilities.GetVirtualMachine(vmName, sourceScope))
{
using (ManagementBaseObject sourceInParams =
sourceService.GetMethodParameters("GetSystemCompatibilityVectors"))
{
sourceInParams["ComputerSystem"] = vm.Path.Path;
using (ManagementBaseObject sourceOutParams =
sourceService.InvokeMethod("GetSystemCompatibilityVectors", sourceInParams, null))
{
WmiUtilities.ValidateOutput(sourceOutParams, sourceScope);
vmCompatibilityVectors = sourceOutParams["CompatibilityVectors"];
}
}
}
//
//Get host compatibility vectors.
//
using (ManagementObject host = WmiUtilities.GetHostComputerSystem(hostName, sourceScope))
{
using (ManagementBaseObject sourceInParams =
sourceService.GetMethodParameters("GetSystemCompatibilityVectors"))
{
sourceInParams["ComputerSystem"] = host.Path.Path;
using (ManagementBaseObject sourceOutParams =
sourceService.InvokeMethod("GetSystemCompatibilityVectors", sourceInParams, null))
{
WmiUtilities.ValidateOutput(sourceOutParams, sourceScope);
hostCompatibilityVectors = sourceOutParams["CompatibilityVectors"];
}
}
}
isCompatible = CompareVectors(vmCompatibilityVectors, hostCompatibilityVectors);
if (isCompatible)
{
Console.WriteLine("The VM and host are compatible.\n");
}
}
}
///
/// Compares the compatibility vectors of the VM with that of the Host.
///
/// The VM's set of compatibility vectors.
/// The Host's set of compatibility vectors.
private static
bool
CompareVectors(
object vmCompatibilityVectors,
object hostCompatibilityVectors
)
{
ManagementBaseObject[] vmVectors = (ManagementBaseObject[])vmCompatibilityVectors;
ManagementBaseObject[] hostVectors = (ManagementBaseObject[])hostCompatibilityVectors;
bool compatible = false;
foreach (ManagementBaseObject vmVector in vmVectors)
{
compatible = false;
foreach (ManagementBaseObject hostVector in hostVectors)
{
if ((uint)vmVector["VectorId"] == (uint)hostVector["VectorId"])
{
compatible = CompareAttributes((VMCompatibility)(uint)(vmVector["CompareOperation"]),
(ulong)vmVector["CompatibilityInfo"],
(ulong)hostVector["CompatibilityInfo"]);
if (compatible == false)
{
Console.WriteLine(String.Format(CultureInfo.InvariantCulture, "\t{0} is Not compatible. VM: {1} !{2} Host: {3}",
vmVector["VectorId"], vmVector["CompatibilityInfo"], vmVector["CompareOperation"], hostVector["CompatibilityInfo"]));
}
break;
}
}
if (compatible == false)
{
//
// The VM is not compatible with the host. So, stop comparing.
//
break;
}
}
return compatible;
}
private static bool CompareAttributes(VMCompatibility vMCompatibility, ulong vmCompatibilityInfo, ulong hostCompatibilityInfo)
{
bool compareResult = false;
switch (vMCompatibility)
{
case VMCompatibility.Equal:
compareResult = vmCompatibilityInfo.Equals(hostCompatibilityInfo);
break;
case VMCompatibility.Disjoint:
if ((vmCompatibilityInfo & hostCompatibilityInfo) == 0)
{
compareResult = true;
}
break;
case VMCompatibility.GreaterThan:
if (vmCompatibilityInfo > hostCompatibilityInfo)
{
compareResult = true;
}
break;
case VMCompatibility.Superset:
if ((vmCompatibilityInfo & hostCompatibilityInfo) == hostCompatibilityInfo)
{
compareResult = true;
}
break;
case VMCompatibility.GreaterThanOrEqual:
if (vmCompatibilityInfo >= hostCompatibilityInfo)
{
compareResult = true;
}
break;
case VMCompatibility.LessThan:
if (vmCompatibilityInfo < hostCompatibilityInfo)
{
compareResult = true;
}
break;
case VMCompatibility.Subset:
if ((vmCompatibilityInfo & hostCompatibilityInfo) == vmCompatibilityInfo)
{
compareResult = true;
}
break;
case VMCompatibility.LessThanOrEqual:
if (vmCompatibilityInfo <= hostCompatibilityInfo)
{
compareResult = true;
}
break;
case VMCompatibility.Multiple:
if ((vmCompatibilityInfo % hostCompatibilityInfo) == 0)
{
compareResult = true;
}
break;
case VMCompatibility.Divisible:
if ((hostCompatibilityInfo % vmCompatibilityInfo) == 0)
{
compareResult = true;
}
break;
default:
Console.WriteLine(String.Format(CultureInfo.InvariantCulture, "Unexpected VMCompatibility option: {0}", vMCompatibility));
break;
}
return compareResult;
}
}
}