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