So while trying to work/modify scripts that already exist; to identify and "remediate if possible" unwanted hardware (Serial, USB, etc...) If found some gotcha type issues. *Previous scripts also based on http://communities.vmware.com/thread/137257 - $VM.ReconfigVM_Task($Spec)
If the target VM has unwanted devices that are only USB controllers, the script will work with out issue (Script generated by Onyx.) It will remove the USB controllers whether the VM is powered on/off
Now if I repeat this process and the VM has some unwanted devices that include USB controllers. Now I also include floppy, serial, and parallel, then the script will error out when I modify it to remove devices based on an list of "unwanted hardware." This happens whether or not I skip over all unwanted hardware that isnt USB. The error comes from the vCenter task & events, not powershell. I even used onyx to compare removing the USB from the GUI and it still gave the same output.
Now this is the slightly modified version that I could use to achieve what I want, if it wouldnt error out:
$NotWantedHardware = "USB|Parallel|Serial|Floppy"
$ConfigureVM=$true
$VMs = Get-VM $args[0]
Write-Host "Unwanted VM hardware Report & Remove."
foreach ($vmx in $VMs){
$vUnwantedHw = @()
$vmxv = $vmx | Get-View
$vmxv.Config.Hardware.Device | where {$_.DeviceInfo.Label -match $NotWantedHardware} | %{
$myObj = "" | select Hardware, Key, RemoveDev
$myObj.Hardware = $_.DeviceInfo.Label
$myObj.Key = $_.Key
if ($vmx.powerstate -notmatch "PoweredOn" -or $_.DeviceInfo.Label -match "USB"){$MyObj.RemoveDev = $true}
else {$MyObj.RemoveDev = $false}
$vUnwantedHw += $myObj | Sort Hardware
}
Write-Host "Here is $($VMX)'s unwanted hardware"
$vUnwantedHw | Select Hardware, @{N="Can be Removed";E="RemoveDev"} | ft -AutoSize #Output for display
if($ConfigureVM){# Unwanted Hardware is configured for removal
$i=0
$vmConfigSpec = New-Object VMware.Vim.VirtualMachineConfigSpec
foreach($dev in $vUnwantedHw){
if($dev.RemoveDev -eq $true){
$vmConfigSpec.DeviceChange += New-Object VMware.Vim.VirtualDeviceConfigSpec
$vmConfigSpec.DeviceChange[$i].device = New-Object VMware.Vim.VirtualDevice
$vmConfigSpec.DeviceChange[$i].device.key = $dev.Key
$vmConfigSpec.DeviceChange[$i].operation = "remove"
$i++
$vmxv.ReconfigVM_Task($vmConfigSpec) #!#New Location, attempting to bypass error
Write-Host "Removed $($dev.Hardware)"
}
}# $vmxv.ReconfigVM_Task($vmConfigSpec) #!#Old location, attempting to bypass error
}# Unwanted Hardware is configured for removal
}
Anyone else face this issue, or do I just have to be content with removing everything while its powered off, while scripting?
I know the SDK Reference says you only need the Key property, but from experience I learned that it is apparently better to pass the complete VirtualDevice object.
Try it like this
$NotWantedHardware = "USB|Parallel|Serial|Floppy"
$ConfigureVM = $true
$VMs = Get-VM $args[0] Write-Host "Unwanted VM hardware Report & Remove."
foreach ($vmx in $VMs){ $vUnwantedHw = @() $vmxv = $vmx | Get-View
$vmxv.Config.Hardware.Device | where {$_.DeviceInfo.Label -match $NotWantedHardware} | %{ $myObj = "" | select Hardware, Key, RemoveDev, Dev
$myObj.Hardware = $_.DeviceInfo.Label
$myObj.Key = $_.Key
$myObj.Dev = $_
if ($vmx.powerstate -notmatch "PoweredOn" -or $_.DeviceInfo.Label -match "USB"){$MyObj.RemoveDev = $true} else {$MyObj.RemoveDev = $false} $vUnwantedHw += $myObj | Sort Hardware
} Write-Host "Here is $($VMX)'s unwanted hardware"
$vUnwantedHw | Select Hardware, @{N="Can be Removed";E="RemoveDev"} | ft -AutoSize #Output for display if($ConfigureVM){# Unwanted Hardware is configured for removal $vmConfigSpec = New-Object VMware.Vim.VirtualMachineConfigSpec
foreach($dev in $vUnwantedHw){ if($dev.RemoveDev -eq $true){ $vmConfigSpec.DeviceChange += New-Object VMware.Vim.VirtualDeviceConfigSpec
$vmConfigSpec.DeviceChange[-1].device = $dev.Dev
$vmConfigSpec.DeviceChange[-1].operation = "remove"
Write-Host "Removed $($dev.Hardware)"
} } $vmxv.ReconfigVM_Task($vmConfigSpec) }# Unwanted Hardware is configured for removal }
Note that the index -1 returns the last entry in an array in PowerShell, avoids having to do this $i variable 🙂
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Did you try disconnecting those devices before removing them ?
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Well this issue came up when removing the USB controller, without any USB devices attached
I know the SDK Reference says you only need the Key property, but from experience I learned that it is apparently better to pass the complete VirtualDevice object.
Try it like this
$NotWantedHardware = "USB|Parallel|Serial|Floppy"
$ConfigureVM = $true
$VMs = Get-VM $args[0] Write-Host "Unwanted VM hardware Report & Remove."
foreach ($vmx in $VMs){ $vUnwantedHw = @() $vmxv = $vmx | Get-View
$vmxv.Config.Hardware.Device | where {$_.DeviceInfo.Label -match $NotWantedHardware} | %{ $myObj = "" | select Hardware, Key, RemoveDev, Dev
$myObj.Hardware = $_.DeviceInfo.Label
$myObj.Key = $_.Key
$myObj.Dev = $_
if ($vmx.powerstate -notmatch "PoweredOn" -or $_.DeviceInfo.Label -match "USB"){$MyObj.RemoveDev = $true} else {$MyObj.RemoveDev = $false} $vUnwantedHw += $myObj | Sort Hardware
} Write-Host "Here is $($VMX)'s unwanted hardware"
$vUnwantedHw | Select Hardware, @{N="Can be Removed";E="RemoveDev"} | ft -AutoSize #Output for display if($ConfigureVM){# Unwanted Hardware is configured for removal $vmConfigSpec = New-Object VMware.Vim.VirtualMachineConfigSpec
foreach($dev in $vUnwantedHw){ if($dev.RemoveDev -eq $true){ $vmConfigSpec.DeviceChange += New-Object VMware.Vim.VirtualDeviceConfigSpec
$vmConfigSpec.DeviceChange[-1].device = $dev.Dev
$vmConfigSpec.DeviceChange[-1].operation = "remove"
Write-Host "Removed $($dev.Hardware)"
} } $vmxv.ReconfigVM_Task($vmConfigSpec) }# Unwanted Hardware is configured for removal }
Note that the index -1 returns the last entry in an array in PowerShell, avoids having to do this $i variable 🙂
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
can't seem to get this working... any updates to it?
Could it be that you ran the script against a VM that has none of the unwanted HW (USB|Parallel|Serial|Floppy) ?
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
It does have the usb controller, I can see it when i do the get-view
There was a <CR><LF> missing from the code, I corrected it.
Can you give it another try ?
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
i'll give it a whirl this afternoon
Where is $args defined?
$args contains the parameters you pass to the script.
Ex: .\script.ps1 value1
Then $args[0] will contain 'value1'
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference