Wednesday, August 8, 2012

Handling Import-VM errors in Server 2012 Hyper-V

Import-VM.  A great cmdlet for Hyper-V.

Couple that being able to import a VM that was not exported and you have a golden feature.

And if all the stars align it works like a charm.  Also notice that in the GUI you import a path, here you import a configuration file.

But, what if you have problems to fix?  It isn’t as straightforward.  You have to fix the source VM to match your host.

Even though there is an example under Get-Help it isn’t easy to visually parse and is difficult to follow, so lets add some color and additional explanation.

 

I have a VM.  That VM was running on Hyper-V Server X and I export a copy and move it to Hyper-V Server Y.

These servers are not set up the same, they are in different environments.

I try Import-VM and get the following results:

Import-VM -Path 'C:\users\Public\VmPxe\Virtual Machines\339C3412-E83F-4EA7-9DE6-F9D388B196E2.XML'

Import-VM : Unable to import virtual machine due to configuration errors.
Please use Compare-VM to repair the virtual machine.
At line:1 char:1
+ Import-VM -Path 'C:\users\Public\VmPxe\Virtual
Machines\339C3412-E83F-4EA7-9DE6- ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~
    + CategoryInfo          : NotSpecified: (:) [Import-VM], VirtualizationOpe
   rationFailedException
    + FullyQualifiedErrorId : Microsoft.HyperV.PowerShell.Commands.ImportVMCom
   mand

Not that error are easy to understand in PowerShell and your mileage varies by the folks that wrote a set, but I at least know that something is wrong and I have another cmdlet to find out what.  Fair enough.

Compare-VM -Path 'C:\users\Public\VmPxe\Virtual Machines\339C3412-E83F-4EA7-9DE6-F9D388B196E2.XML'


VM                 : Microsoft.HyperV.PowerShell.VirtualMachine
OperationType      : ImportVirtualMachine
Destination        : BJELKS4
Path               : C:\users\Public\VmPxe\Virtual
                     Machines\339C3412-E83F-4EA7-9DE6-F9D388B196E2.XML
SnapshotPath       : C:\users\Public\VmPxe\Snapshots
VhdDestinationPath :
VhdSourcePath      :
Incompatibilities  : {33012, 33012}

Excellent, I have incompatibilities 33012, twice.  What is that all about???  I guess that I need to capture that report to see the errors as I can see that it is in an array ( the {} told me so ).

$compareResult = Compare-VM -Path 'C:\users\Public\VmPxe\Virtual Machines\339C3412-E83F-4EA7-9DE6-F9D388B196E2.XML'

$compareResult.Incompatibilities

Message                                     MessageId Source
-------                                     --------- ------
Could not find Ethernet...                      33012 Microsoft.HyperV.Power...
Could not find Ethernet...                      33012 Microsoft.HyperV.Power...

$compareResult.Incompatibilities[0].Message
Could not find Ethernet switch 'VMs'.

Okay, some useful information.  Now, I need to fix that.  But how?  I have a Message, MessageId, and a Source.  I bet the Source is a Source object that can be acted upon. <light bulb on>

Lets just try to disconnect the VM from the virtual switch, but how? 

If I look at the –Examples under Get-Help I scan through and see that I can take this $compareResult and act upon the .Source objects.  What I have declared as variable $compareResult MSFT refers to as a “Compatibility Report”.  But the important part is that it is more than a report.

That array of objects behind $compareResult.Incompatibilities are actually objects.  They are references to the objects that are having problems.  Even though it began as an XML file.

In my case these are the VMNetworkAdapter objects of the VM that I am attempting to import.  So I can’t search on the name of the VMNetworkAdapter and are forced to work through the list of objects.  At this time it is a kind of temporary VM that is in a state of limbo, it is declared but not committed.

Lets work through and fix the VM that I am attempting to import.

$compareResult.Incompatibilities[0].Source | Disconnect-VMNetworkAdapter

Okay, that Disconnected one of the VMNetworkAdapaters, but I want to connect the other one to the proper Virtual Switch.

$compareResult.Incompatibilities[1].Source | Connect-VMNetworkAdapter -SwitchName "Virtual Network0"

compare-VM -CompatibilityReport $compareResult


VM                 : Microsoft.HyperV.PowerShell.VirtualMachine
OperationType      : ImportVirtualMachine
Destination        : BJELKS4
Path               : C:\users\Public\VmPxe\Virtual
                     Machines\339C3412-E83F-4EA7-9DE6-F9D388B196E2.XML
SnapshotPath       : C:\users\Public\VmPxe\Snapshots
VhdDestinationPath :
VhdSourcePath      :
Incompatibilities  :

Okay, looking good, no errors.  No what?  How do I import this silly Compatibility Report that I just modified?

Well, the option is there.

Import-VM -CompatibilityReport $compareResult

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

My only big comment on this is that I have to act upon each individual .Incompatibilities.Message in the array on a case by case basis.  That is a bit of a pain.  And it took a while.  Especially because you have to be a bit familiar with the available PowerShell cmdlets to know what you might be able to apply to any particular object.

Seems that I need a script to automatically manage the incompatibilities…

3 comments:

james robinson said...

This Post was insanely useful for me! Thanks for describing your thought process as you go along. Really helped in understanding what i was doing and not just retyping text.
Got my DC moved to my new Hyper-v server. Thanks again!!

BrianEh said...

Thank you.
I always think it is important for folks to understand the whats and whys.
I know that some folks in the forums don't appreciate this and just what a quick point and click answer, but I try to tell them why anyway. ;-)

Konstantinos Vasileiou said...

many COngs! very usefull!!