Attaching a VHD To A VM Using The Hyper-V WMI V2 Namespace


Relating to all my recent posts on the WMI V2 namespace here’s another one for attaching a VHD to a VM.  It looks like a lot of code but a lot of it is duplicated (so if you where writing an application you can factor it pretty easily).  There are effectively two steps to this process, the first is to add a synthetic disk drive and the second is to connect that disk drive to the actual VHD.

 

Attaching A VHD To A VM

$vmName = "Test" 
$vhdPath = "d:\vms\Test.vhdx"

 #Retrieve the Hyper-V Management Service, ComputerSystem class for the VM and the VM’s SettingData class. 
$Msvm_VirtualSystemManagementService = Get-WmiObject -Namespace root\virtualization\v2 `
      -Class Msvm_VirtualSystemManagementService 

$Msvm_ComputerSystem = Get-WmiObject -Namespace root\virtualization\v2 `
      -Class Msvm_ComputerSystem -Filter "ElementName='$vmName'" 

$Msvm_VirtualSystemSettingData = ($Msvm_ComputerSystem.GetRelated("Msvm_VirtualSystemSettingData", `
     "Msvm_SettingsDefineState", `
      $null, `
      $null, ` 
     "SettingData", `
     "ManagedElement", `
      $false, $null) | % {$_}) 


#Retrieve the default (primordial) resource pool for Synthetic Disk Drive’s
$Msvm_ResourcePool = Get-WmiObject -Namespace root\virtualization\v2 -Class Msvm_ResourcePool `
    -Filter "ResourceSubType = 'Microsoft:Hyper-V:Synthetic Disk Drive' and Primordial = True"

#Retrieve the AllocationCapabilities class for the Resource Pool
$Msvm_AllocationCapabilities = ($Msvm_ResourcePool.GetRelated("Msvm_AllocationCapabilities", `
    "Msvm_ElementCapabilities", `
    $null, `
    $null, `
    $null, `
    $null, `
    $false, `
    $null) | % {$_})

#Query the relationships on the AllocationCapabilities class and find the default class (ValueRole = 0)
$Msvm_SettingsDefineCapabilities = ($Msvm_AllocationCapabilities.GetRelationships(`
    "Msvm_SettingsDefineCapabilities") | Where-Object {$_.ValueRole -eq "0"})

#The PartComponent is the Default Msvm_StorageAllocationSettingData class values
$Msvm_StorageAllocationSettingDataTemplate = [WMI]$Msvm_SettingsDefineCapabilities.PartComponent

#Clone the default settings
$Msvm_StorageAllocationSettingData = $Msvm_StorageAllocationSettingDataTemplate.Clone()

#Find the IDE Controller To Connect The Disk To 
$IdeController = $Msvm_VirtualSystemSettingData.GetRelated("Msvm_ResourceAllocationSettingData") | Where-Object {
    ($_.ResourceType -eq 5) -and ($_.ResourceSubType -eq "Microsoft:Hyper-V:Emulated IDE Controller") -and ($_.Address -eq 0)} 

#Specify the disk drives connection point and address (location on the controller)
$Msvm_StorageAllocationSettingData.Parent = $IdeController
$Msvm_StorageAllocationSettingData.AddressOnParent = 0

#Add the drive to the VM and save the resulting disk drive path
$diskDriveResource = ($Msvm_VirtualSystemManagementService.AddResourceSettings($Msvm_VirtualSystemSettingData, `
    $Msvm_StorageAllocationSettingData.GetText(2)).ResultingResourceSettings)


#Retrieve the default (primordial) resource pool for Virtual Hard Disk’s
$Msvm_ResourcePool = Get-WmiObject -Namespace root\virtualization\v2 -Class Msvm_ResourcePool `
    -Filter "ResourceSubType = 'Microsoft:Hyper-V:Virtual Hard Disk' and Primordial = True"

#Retrieve the AllocationCapabilities class for the Resource Pool
$Msvm_AllocationCapabilities = ($Msvm_ResourcePool.GetRelated("Msvm_AllocationCapabilities", `
    "Msvm_ElementCapabilities", `
    $null, `
    $null, `
    $null, `
    $null, `
    $false, `
    $null) | % {$_})

#Query the relationships on the AllocationCapabilities class and find the default class (ValueRole = 0)
$Msvm_SettingsDefineCapabilities = ($Msvm_AllocationCapabilities.GetRelationships(`
    "Msvm_SettingsDefineCapabilities") | Where-Object {$_.ValueRole -eq "0"})

#The PartComponent is the Default Msvm_StorageAllocationSettingData class values
$Msvm_StorageAllocationSettingDataTemplate = [WMI]$Msvm_SettingsDefineCapabilities.PartComponent

#Clone the default settings
$Msvm_StorageAllocationSettingData = $Msvm_StorageAllocationSettingDataTemplate.Clone()

#Specify the VHD's Disk Drive and Path (location on the controller)
$Msvm_StorageAllocationSettingData.Parent = $diskDriveResource
$Msvm_StorageAllocationSettingData.HostResource = @($vhdPath)

#Add the VHD to the disk drive
$Msvm_VirtualSystemManagementService.AddResourceSettings($Msvm_VirtualSystemSettingData, `
    $Msvm_StorageAllocationSettingData.GetText(2))

-Taylor Brown

-Program Manager, Hyper-V


Comments (7)

  1. Michael Fruchtman says:

    I modified the above script slightly to attach a new vhdx to IDE 1 of a VM in Windows Server 2012.  The script succeeds until the very last call when the Job reports back error 32773 (Invalid parameter) and the string: "'Win8.1Preview' failed to add resources. (Virtual machine ID BD4F6962-7FCA-434A-9868-165176208EB5)."  I've double checked the path of the vhdx and it is correct.  Any idea what is going wrong?

  2. Which specific line did you modify?  Also is the VM running at the time you are trying to configure the VHD?

  3. Artho Vissuti says:

    I too am getting a similar error when attempting to add a VHD to a (powered off) VM in 2012.  It seems to fail adding the 'Microsoft:Hyper-V:Synthetic Disk Drive'

    When calling the line:

    $diskDriveResource = ($Msvm_VirtualSystemManagementService.AddResourceSettings($Msvm_VirtualSystemSettingData, `

       $Msvm_StorageAllocationSettingData.GetText(2)).ResultingResourceSettings)

    I get the error 32768, with the following error string:

    "'TestVM' failed to add device 'Synthetic Disk Drive'. (Virtual machine ID 90C819E8-1A1C-4FDE-A090-70D93F67EB01)"

    Any help would be greatly appreciated!

  4. rakesh gowda n says:

    Hey guys,

     I am trying to convert the same script to c# code However I got  stucked at [WMI]$Msvm_SettingsDefineCapabilities.PartComponent . How to acheive this .

    I mean $Msvm_SettingsDefineCapabilities.PartComponent is a string object and how to convert it to WMI.

  5. Aneesh says:

    Any one please give Suggestion to add SCSI Hard disk

  6. David Elins says:

    Hello everyone –

    I'm trying to convert this script to java using j-interop. Any pointers would be appreciated.

  7. Cory says:

    Do you have this in C#, I've been having a very difficult time attempting to convert it to C#.