IgnitionUSMC
Contributor
Contributor

Removing Unwanted Hardware from VM, while powered on. -issues

Jump to solution

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?

0 Kudos
1 Solution

Accepted Solutions
LucD
Leadership
Leadership

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

View solution in original post

0 Kudos
10 Replies
LucD
Leadership
Leadership

Did you try disconnecting those devices before removing them ?


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
IgnitionUSMC
Contributor
Contributor

Well this issue came up when removing the USB controller, without any USB devices attached

0 Kudos
LucD
Leadership
Leadership

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

0 Kudos
esarakaitis
Enthusiast
Enthusiast

can't seem to get this working... any updates to it?

Exception calling "ReconfigVM_Task" with "1" argument(s): "
Required property device is missing from data object of type VirtualDeviceConfigSpec
while parsing serialized DataObject of type vim.vm.device.VirtualDeviceSpec
at line 1, column 302
while parsing property "deviceChange" of static type ArrayOfVirtualDeviceConfigSpec
while parsing serialized DataObject of type vim.vm.ConfigSpec
at line 1, column 296
while parsing call information for method ReconfigVM_Task
at line 1, column 218
while parsing SOAP body
at line 1, column 207
while parsing SOAP envelope
at line 1, column 38
while parsing HTTP request for method reconfigure
on object of type vim.VirtualMachine
at line 1, column 0"
At line:28 char:26
+     $vmxv.ReconfigVM_Task <<<< ($vmConfigSpec)
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : DotNetMethodException
0 Kudos
LucD
Leadership
Leadership

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

0 Kudos
esarakaitis
Enthusiast
Enthusiast

It does have the usb controller, I can see it when i do the get-view

0 Kudos
LucD
Leadership
Leadership

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

0 Kudos
esarakaitis
Enthusiast
Enthusiast

i'll give it a whirl this afternoon

0 Kudos
likeahoss
Enthusiast
Enthusiast

Where is $args defined?

0 Kudos
LucD
Leadership
Leadership

$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

0 Kudos