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

  • Anonymous
    August 26, 2013
    The comment has been removed

  • Anonymous
    August 26, 2013
    The comment has been removed

  • Anonymous
    September 03, 2013
    The comment has been removed

  • Anonymous
    October 28, 2013
    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.

  • Anonymous
    April 20, 2014
    Any one please give Suggestion to add SCSI Hard disk

  • Anonymous
    August 04, 2014
    Hello everyone - I'm trying to convert this script to java using j-interop. Any pointers would be appreciated.

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