VMware {code} Community
RegularAdmin
Contributor
Contributor

Add Host USB Device to VM via powercli script

Hi everyone,

Summary:

I'm facing the issue when: Trying to connect a specific (physical) USB device (USB token) to specific VM.
In vCenter web-client everything works properly. Standard process is:

  • vCenter - Choose my VM - Edit Settings - Add new device - Host USB Device

Automatically is created USB controller (USB 2) and under this controller is assigned USB device. The device connected that way is working properly.

But what if I want do same thing via script?

------------------

Some basic data first:

We're running on: vCenter (7.0.3.00300) and ESXi (7.0.3, build: 19898904)

We're using specific USB token, so here's the lsusb output

 

 

 

lsusb 
Bus 001 Device 001: ID 0e0f:8003 VMware, Inc. Root Hub
Bus 001 Device 002: ID 0529:0003 Aladdin Knowledge Systems 
Bus 001 Device 003: ID 0557:7000 ATEN International Co., Ltd Hub
Bus 001 Device 004: ID 0557:2419 ATEN International Co., Ltd Virtual mouse/keyboard device

 

 

 

Also there is the command for passthrough of USB devices, but in this case is useless.

 

 

 

esxcli hardware usb passthrough device list

 

 

 

I repeat, it works properly in when it's set via web-gui. 🙂

------------------

Power-Cli:

So. powercli have a powerful module VMware.VimAutomation.Core which using following API calls to handling USB devices:

  • Data Object - VirtualUSB(vim.vm.device.VirtualUSB) - link

So, in the powercli should be a possible determine the physical device which needs to be connected to VM by a several ways when you using DeviceBacking:

  • Data Object - VirtualUSBUSBBackingInfo(vim.vm.device.VirtualUSB.USBBackingInfo) - link
  • Data Object - VirtualUSBRemoteHostBackingInfo(vim.vm.device.VirtualUSB.RemoteHostBackingInfo) - link
  • Data Object - VirtualDeviceDeviceBackingInfo(vim.vm.device.VirtualDevice.DeviceBackingInfo) - link

Which means that you can write deviceName like this:

 

 

 

# by physical path
path:0/1/0

# by pid and vid which is vendor id and product id
pid:0529 vid:0003

# by combination of above listed
pid:0529 vid:0003 hostId:00\ 00\ 00\ 00\ 00\ 00\ 00\ 00-00\ 00\ 3c\ ec\ ef\ 4b\ f0\ a4
# or
path:0/1/0 hostId:00\ 00\ 00\ 00\ 00\ 00\ 00\ 00-00\ 00\ 3c\ ec\ ef\ 4b\ f0\ a4

 

 

 

However:

Physical path on the bus not working! Because the path which is listed in vCenter is not same as the data listed in lsusb (see below).

Path (same as in vCenter) should be writen into the vmkernel.log but is't not! Not even in gzipped logs which rotated out already. So I cannot catch the same address which vCenter requires.

I was trying "re-build" the path from information which I can accessible now, so from lsusb because the command have some next interesting parameters. But honestly I have no clue how VMware generating the path from these information:

 

 

lsusb -d 0529:0003 -v
Bus 001 Device 002: ID 0529:0003 Aladdin Knowledge Systems 
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
  bDeviceClass            0 (Defined at Interface level)
  bDeviceSubClass         0 
  bDeviceProtocol         0 
  bMaxPacketSize0        64
  idVendor           0x0529 Aladdin Knowledge Systems
  idProduct          0x0003 
  bcdDevice            6.09
  iManufacturer           1 Gemalto
  iProduct                2 Sentinel HL
  iSerial                 0 
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength       0x0022
    bNumInterfaces          1
    bConfigurationValue     1
    iConfiguration          0 
    bmAttributes         0x80
      (Bus Powered)
    MaxPower               50mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           1
      bInterfaceClass         3 Human Interface Device
      bInterfaceSubClass      0 No Subclass
      bInterfaceProtocol      0 None
      iInterface              0 
        HID Device Descriptor:
          bLength                 9
          bDescriptorType        33
          bcdHID               1.10
          bCountryCode            0 Not supported
          bNumDescriptors         1
          bDescriptorType        34 Report
          wDescriptorLength     116
         Report Descriptors: 
           ** UNAVAILABLE **
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x85  EP 5 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval             255
can't get device qualifier: Resource temporarily unavailable
Device Status:     0x0000
  (Bus Powered)

 

 

Then I said: Maybe just pair bus and dev number from this output. No success.

 

 

lsusb -t
Bus#  1
`-Dev#   1 Vendor 0x0e0f Product 0x8003
  |-Dev#   2 Vendor 0x0529 Product 0x0003
  `-Dev#   3 Vendor 0x0557 Product 0x7000
    `-Dev#   4 Vendor 0x0557 Product 0x2419

 

 

So I definitely escape the idea that the "path" is detectable from anywhere from VMware.

Funny thing is, that VMware, respectively ESXi, have a file /var/log/usb.log. Why the information about path isn't printed in this file? It would be so much more transparent.

------------------

Only one option left: Identify device via pid and vid which can be discovered again via lsusb command.

Output of command for device is:

 

 

Bus 001 Device 002: ID 0529:0003 Aladdin Knowledge Systems

 

 

------------------

So here's the powercli script, which should add USB controller to desired VM first and after that add physical device.

First part of the script working fine:

 

 

$spec = New-Object VMware.Vim.VirtualMachineConfigSpec 
$deviceCfg = New-Object VMware.Vim.VirtualDeviceConfigSpec
$deviceCfg.Operation = "add"
$deviceCfg.Device = New-Object VMware.Vim.VirtualUSBController
$deviceCfg.Device.Key = -1
$deviceCfg.Device.Connectable = New-Object VMware.Vim.VirtualDeviceConnectInfo
$deviceCfg.Device.Connectable.StartConnected - $true
$deviceCfg.Device.Connectable.AllowGuestControl = $false
$deviceCfg.Device.Connectable.Connected = $true
$deviceCfg.Device.ControllerKey = 100
$deviceCfg.Device.BusNumber = -1
$deviceCfg.Device.autoConnectDevices = $true

$spec.DeviceChange += $deviceCfg

$vm_name = "vm-01"
$vm = get-vm -Name $vm_name | Get-View
$vm.ReconfigVM_Task($spec)

 

 

 USB 2.0 controller is successfully added.

Second part of script:

 

 

# cleaning the vars
$spec = $null
$deviceCfg = $null

# define vm
$vm_name = "vm-01"

# define pid of phy device
$devicePid = "0529"
# define vid of phy device
$deviceVid = "0003"

$spec = New-Object VMware.Vim.VirtualMachineConfigSpec 
$deviceCfg = New-Object VMware.Vim.VirtualDeviceConfigSpec[] (1)
$deviceCfg[0] = New-Object VMware.Vim.VirtualDeviceConfigSpec
$deviceCfg[0].Operation = "add"
$deviceCfg[0].Device = New-Object VMware.Vim.VirtualUSB
$deviceCfg[0].Device.backing = New-Object VMware.Vim.VirtualUSBUSBBackingInfo
$deviceCfg[0].Device.backing.deviceName = "pid:$devicePid vid:$deviceVid"
$deviceCfg[0].Device.backing.useAutoDetect = $null
$deviceCfg[0].Device.connectable = $null
$deviceCfg[0].Device.connected = $true
$deviceCfg[0].Device.vendor = 3
$deviceCfg[0].Device.vendor = 1321
$deviceCfg[0].Device.SlotInfo = $null
$deviceCfg[0].Device.family = "hid"
$deviceCfg[0].Device.speed = "full"

$vm = get-vm -Name $vm_name | Get-View
$vm.ReconfigVM_Task($spec)

 

 

Script exited correctly, but nothing's do. The task is processed in vCenter, but with no changes on the VM.

This is output in vCenter in tasks:

 

 

Reconfigured vm-01 on esxi-03 in pgr-dc. Modified: Added: Deleted:

 

 

And when the USB device is added via vCenter, the output is:

 

 

Reconfigured vm-01 on esxi-03 in prg-dc. Modified: config.hardware.device(7000).device: () -> (41000); config.extraConfig("usb.autoConnect.device0").value: "" -> "path:0/1/0 autoclean:1 virtPath:usb.autoConnect.device0 version:4"; Added: config.hardware.device(41000): (key = 41000, deviceInfo = (label = "USB 41001", summary = "Aladdin Knowledge Sentinel HL"), backing = (deviceName = "path:0/1/0", useAutoDetect = <unset>), connectable = null, slotInfo = null, controllerKey = 7000, unitNumber = 41000, numaNode = <unset>, connected = true, vendor = 1321, product = 3, family = ("hid"), speed = ("full")); Deleted:

 

 

 

I missing something but I can't find it anymore. Or I just completely lost.

Maybe it would be more readable for someone else.

I would be grateful for any hint.

Thanks,

John

0 Kudos
3 Replies
LucD
Leadership
Leadership

Is this a PowerCLI question or an API question?
If you want I can move this thread to the VMware{code} Discussions




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

0 Kudos
LucD
Leadership
Leadership

To me, it looks as if you using the API via the PowerCLI framework, so it is a bit of an in-between question.

Let's see if in the {code} community someone can help, if not, we can always move the thread back here.

Update: the move seems to have lost your last reply.


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

0 Kudos
RegularAdmin
Contributor
Contributor

Yeah, it seems so. But it's okay. Thanks for moving post to correct section and I am sorry for posting to wrong.

0 Kudos