Adding physical pass-through disks and language-fix

May 14, 2009 at 7:37 AM
Edited May 14, 2009 at 7:41 AM


first thanks for this library, I like it.

One thing I've missed: adding physical passthrough disks to a VM.
I found a statement within the documentation of Function Add-VMDISK (...or the path to a passthrough disk), but I did not figure out how to use this.

VHD Images are added like this: VMController-->VMDrive-->VMDisk, but passthroughs seems to be added like VMController-->VMDrive where the physical disk is added via HostResources property of the drive.
So I extendet the Function Add-VMDRIVE like you can see below. The new parameter -PHYSDISK can take a value which identifies the drive to be used (this has to be offline first!!).
The Value can be a numeric one (this is the number you can see in drive manager), or an asterisk (*), where the first possible drive found will be used.
Example: Add-VMDRIVE -vm vServer -Controller 0 -LUN 0 -PHYSDISK 3 -SCSI

I am very new to PowerShell and WMI, so the code might be from a bad quality. Maybe someone can make it better.

There is a second thing I found, which someone else has mentioned here before.
In Function Get-VM, which seems to be used by many other functions, there is a string-match (Caption Like 'Virtual%') which failes on german setups, too.
The string is 'Virtuelle Maschine', so I shortened the match to 'Virtu%'. If I remember, for france setups this will not wort either, because the word 'Virtuel' ist the second one, so is has to be '%Virtu%' there...
It was not so easy to find this simple cause, but fixing is easy if you know about it, so I think it would be good to document this for others.



Filter Add-VMDRIVE
{Param ($VM , $ControllerID=0 , $LUN, $Server="." , $PHYSDISK="" ,  [switch]$DVD , [switch]$SCSI)
 if ($VM -eq $null) {$VM=$_}
 if ($VM -is [String]) {$VM=(Get-VM -Name $VM -Server $server) }
 if ($VM -is [Array]) {if ($DVD) {$VM | ForEach-Object {Add-VMDRIVE -VM $_ -ControllerID $ControllerID -LUN $LUN -server $server  -DVD} }
                           else  {if ($scsi) {$VM | ForEach-Object {Add-VMDRIVE -VM $_ -ControllerID $ControllerID -LUN $LUN -server $server} }
                        else {$VM | ForEach-Object {Add-VMDRIVE -VM $_ -ControllerID $ControllerID -LUN $LUN -server $server -SCSI } } }}
 # think of this as a container into which we mount a virtual disk - makes more sense with DVDs (DVD drive and DVD disk) than Hard disks
 if ($VM -is [System.Management.ManagementObject]) {
     #Step 1. Get Resource Allocation Setting Data object for a disk, set it's parent to the Controller and the Address to the "Lun"
     if ($DVD)                 {$diskRASD=NEW-VMRasd -ResType 16 -ResSubType 'Microsoft Synthetic DVD Drive' -Server $VM.__Server }
     elseif ($PHYSDISK -ne "") {$diskRASD=NEW-VMRasd -ResType 22 -ResSubType 'Microsoft Physical Disk Drive'  -Server $VM.__Server }
     else                      {$diskRASD=NEW-VMRasd -ResType 22 -ResSubType 'Microsoft Synthetic Disk Drive'  -Server $VM.__Server }
     if ($SCSI) {$diskRASD.parent=(Get-VMDiskController -vm $vm -ControllerID $ControllerID -SCSI).__Path }
     else       {$diskRASD.parent=(Get-VMDiskController -vm $vm -ControllerID $ControllerID -IDE).__Path  }
     if ($PHYSDISK -ne "") {
         $query = "SELECT * FROM Msvm_DiskDrive"
        if ($PHYSDISK -ne "*") {$query += " WHERE DriveNumber = " + $PHYSDISK}
        $PD = Get-WmiObject -NameSpace "root\virtualization" -Query "$query" | select-object -first 1
        $diskRASD.HostResource = $PD.__PATH
     $arguments = @($VM.__Path, @( $diskRASD.psbase.GetText([System.Management.TextFormat]::WmiDtd20) ), $null, $null )
     $VSMgtSvc=Get-WmiObject -ComputerName $VM.__server -NameSpace  "root\virtualization" -Class "MsVM_virtualSystemManagementService"
     $result=$VSMgtSvc.psbase.invokeMethod("AddVirtualSystemResources", $arguments)  
     if ($result -eq 0) {"Added drive to '$($vm.elementName)'."} else {"Failed to add drive to '$($vm.elementName)', result code: $result."} }


Jun 7, 2009 at 9:54 AM

Alex I've written something very similar except it is a seperate add passthru function and this will posted in an update shortly.