Lxd usb device and required keyword

I have a usb device for which i have set required to false like so,

  webcam0:
    mode: "0777"
    path: /dev/webcam0
    required: "false"
    type: unix-char

The required property should be boolean as mentioned here. However, it turns to string (has quotes around it) and doesnt seem to work. Is this the correct syntax?

I am using app-emulation/lxd-3.0.0-r1 on gentoo.

There is USB passthrough support,

https://stgraber.org/2017/03/27/usb-hotplug-with-lxd-containers/

I do not know why you get that issue with the char device.

I added the device like so,

lxc config device add zmvm webcam0 unix-char mode=0777 path=/dev/webcam0 required=false

but on starting the container i get,

$ lxc start zmvm
Error: not a directory
Try `lxc info --show-log zmvm` for more info

Log shows

$ lxc info --show-log zmvm |tail -30
lxc 20180701132951.748 TRACE    lxc_commands - commands.c:lxc_cmd:311 - Connection refused - Command "get_state" failed to connect command socket
lxc 20180701132951.759 INFO     lxc_confile - confile.c:set_config_idmaps:1653 - Read uid map: type u nsid 0 hostid 1000000 range 65536
lxc 20180701132951.759 INFO     lxc_confile - confile.c:set_config_idmaps:1653 - Read uid map: type g nsid 0 hostid 1000000 range 65536
lxc 20180701132951.761 TRACE    lxc_commands - commands.c:lxc_cmd:311 - Connection refused - Command "get_cgroup" failed to connect command socket
lxc 20180701132951.761 TRACE    lxc_commands - commands.c:lxc_cmd:311 - Connection refused - Command "get_state" failed to connect command socket
lxc 20180701133035.861 TRACE    lxc_commands - commands.c:lxc_cmd:311 - Connection refused - Command "get_cgroup" failed to connect command socket
lxc 20180701133035.861 TRACE    lxc_commands - commands.c:lxc_cmd:311 - Connection refused - Command "get_state" failed to connect command socket
lxc 20180701133035.870 INFO     lxc_confile - confile.c:set_config_idmaps:1653 - Read uid map: type u nsid 0 hostid 1000000 range 65536
lxc 20180701133035.870 INFO     lxc_confile - confile.c:set_config_idmaps:1653 - Read uid map: type g nsid 0 hostid 1000000 range 65536
lxc 20180701133035.871 TRACE    lxc_commands - commands.c:lxc_cmd:311 - Connection refused - Command "get_cgroup" failed to connect command socket
lxc 20180701133035.871 TRACE    lxc_commands - commands.c:lxc_cmd:311 - Connection refused - Command "get_state" failed to connect command socket
lxc 20180701133051.547 TRACE    lxc_commands - commands.c:lxc_cmd:311 - Connection refused - Command "get_cgroup" failed to connect command socket
lxc 20180701133051.547 TRACE    lxc_commands - commands.c:lxc_cmd:311 - Connection refused - Command "get_state" failed to connect command socket
lxc 20180701133051.556 TRACE    lxc_commands - commands.c:lxc_cmd:311 - Connection refused - Command "get_cgroup" failed to connect command socket
lxc 20180701133051.556 TRACE    lxc_commands - commands.c:lxc_cmd:311 - Connection refused - Command "get_state" failed to connect command socket
lxc 20180701133051.556 TRACE    lxc_commands - commands.c:lxc_cmd:311 - Connection refused - Command "get_cgroup" failed to connect command socket
lxc 20180701133051.556 TRACE    lxc_commands - commands.c:lxc_cmd:311 - Connection refused - Command "get_state" failed to connect command socket
lxc 20180701133127.213 TRACE    lxc_commands - commands.c:lxc_cmd:311 - Connection refused - Command "get_cgroup" failed to connect command socket
lxc 20180701133127.213 TRACE    lxc_commands - commands.c:lxc_cmd:311 - Connection refused - Command "get_state" failed to connect command socket
lxc 20180701133127.218 TRACE    lxc_commands - commands.c:lxc_cmd:311 - Connection refused - Command "get_cgroup" failed to connect command socket
lxc 20180701133127.218 TRACE    lxc_commands - commands.c:lxc_cmd:311 - Connection refused - Command "get_state" failed to connect command socket
lxc 20180701133127.218 TRACE    lxc_commands - commands.c:lxc_cmd:311 - Connection refused - Command "get_cgroup" failed to connect command socket
lxc 20180701133127.218 TRACE    lxc_commands - commands.c:lxc_cmd:311 - Connection refused - Command "get_state" failed to connect command socket
lxc 20180701133132.120 TRACE    lxc_commands - commands.c:lxc_cmd:311 - Connection refused - Command "get_cgroup" failed to connect command socket
lxc 20180701133132.120 TRACE    lxc_commands - commands.c:lxc_cmd:311 - Connection refused - Command "get_state" failed to connect command socket
lxc 20180701133132.125 TRACE    lxc_commands - commands.c:lxc_cmd:311 - Connection refused - Command "get_cgroup" failed to connect command socket
lxc 20180701133132.125 TRACE    lxc_commands - commands.c:lxc_cmd:311 - Connection refused - Command "get_state" failed to connect command socket
lxc 20180701133132.125 TRACE    lxc_commands - commands.c:lxc_cmd:311 - Connection refused - Command "get_cgroup" failed to connect command socket
lxc 20180701133132.125 TRACE    lxc_commands - commands.c:lxc_cmd:311 - Connection refused - Command "get_state" failed to connect command socket

Try with ‘usb’ instead of ‘unix-char’.

I do not know whether it was ever possible to use unix-char in such a case.
With ‘usb’, the device disappears from the host and is there to use exclusively by the container.

ok. On the host i see the device,

Bus 004 Device 005: ID 045e:076d Microsoft Corp. LifeCam HD-5000

$v4l2-ctl --list-devices
Microsoft® LifeCam HD-5000 (usb-0000:00:14.0-10):
/dev/video0

I add the device using,

$ lxc config device add zmvm webcam0 usb vendorid=045e productid=076d required=false
Device webcam0 added to zmvm

but in the container i dont see the device

$ lxc exec zmvm /bin/bash
root@zmvm:~# ls -la /dev/vi*
ls: cannot access '/dev/vi*': No such file or directory

Please upgrade to 3.0.1, there was a number of issues with that particular feature in 3.0.0.

Unfortunately, gentoo does not have the 3.0.1 package. It has 3.1 and 3.2 packages though. Which one is recommended to upgrade from 3.0.0?

I believe both 3.1 and 3.2 will have the fix you’re looking for, so I’d just go with 3.2 then.

I upgraded to version 3.2,

$lxd --version
3.2

The usb webcam is added to the container,

  webcam0:
    productid: 076d
    required: "false"
    type: usb
    vendorid: 045e

However, there is no sight of it in the container.
# ls -la /dev/vi*
ls: cannot access ‘/dev/vi*’: No such file or directory

On the other hand it is still listed on the host,

# v4l2-ctl --list-devices
Microsoft® LifeCam HD-5000 (usb-0000:00:14.0-10):
    /dev/video0

Isnt it supposed to detach from the host and available exclusively to the container?

I suppose you are using the snap package of lxd.

The LXD snap uses the system-observe plug in order to listen to the events about adding and removing USB devices.

Is it shown in snap interfaces lxd?

No, the host is running gentoo linux. I have set LXD_DIR=/var/snap/lxd/common/lxd in the LXD startup script.

Here is how to debug this issue:

  1. Suppose the container name is mycontainer. The logs can then be found in /var/log/lxd/mycontainer/
  2. Towards the end of lxc.conf (in /var/log/lxd/mycontainer/), it should have a lxc.mount line relating to the USB device. This line should show where, in the container, you can find the USB device. Something like dev/bus/usb/001/002. Corresponds to /dev/bus/usb/001/002 in the container. Check if this exists.
  3. Then, lxc.log (in /var/log/lxd/mycontainer/) should have lines that confirm that the device has been mounted or an error appeared. Looks for lines that mention usb or the device name you gave when configuring in the beginning.

My lxc.conf looks like this,

# tail -1 /var/snap/lxd/common/lxd/logs/zmvm/lxc.conf 
lxc.mount.entry = /var/snap/lxd/common/lxd/devices/zmvm/unix.webcam0.dev-bus-usb-004-002 dev/bus/usb/004/002 none bind,create=file

lsusb on the host shows the same device id’s,
Bus 004 Device 002: ID 045e:076d Microsoft Corp. LifeCam HD-5000
so the device definition is correct.

Finally the log file shows,

# grep -E 'webcam|usb' /var/snap/lxd/common/lxd/logs/zmvm/lxc.log
lxc zmvm 20180705222140.948 DEBUG    lxc_conf - conf.c:mount_entry:1965 - Remounting "/var/snap/lxd/common/lxd/devices/zmvm/unix.webcam0.dev-bus-usb-004-002" on "/var/lib/lxc/rootfs/dev/bus/usb/004/002" to respect bind or remount options
lxc zmvm 20180705222140.948 DEBUG    lxc_conf - conf.c:mount_entry:1986 - Flags for "/var/snap/lxd/common/lxd/devices/zmvm/unix.webcam0.dev-bus-usb-004-002" were 0, required extra flags are 0
lxc zmvm 20180705222140.948 DEBUG    lxc_conf - conf.c:mount_entry:2042 - Mounted "/var/snap/lxd/common/lxd/devices/zmvm/unix.webcam0.dev-bus-usb-004-002" on "/var/lib/lxc/rootfs/dev/bus/usb/004/002" with filesystem type "none"

The log seems to indicate the device is mounted correctly. In the container i see,

# ls -la /dev/bus/usb/004/002 
crw-rw-r-- 1 root root 189, 385 Jul  6 03:51 /dev/bus/usb/004/002
# v4l2-ctl --list-devices -d /dev/bus/usb/004/002 
VIDIOC_QUERYCAP: failed: Inappropriate ioctl for device
/dev/bus/usb/004/002: not a v4l2 node

Why dont i get a /dev/video0 though?

The container is running Ubuntu 16.04.4 LTS.

Okay, I tried it myself with LXD 3.2 (from snap) and I can replicate what you get there.
That is, the USB device appears partially in the container but does not get fully transferred to the container.

Specifically, if you run the following on both the host and the container (replace 003/008 accordingly), you get some information in the container but not as much as on the host.

udevadm info --name /dev/bus/usb/003/008

It is udev that runs in the container that should set up /dev/video0 and whatever else is required.

When I tried a few weeks ago (vaguely remember I was using LXD 3.1/snap), it worked fine and was quite stable. I had a quick look on the git repository (files lxc_container.go, devices.go) and could only see some non-critical changes in early May.

I think this warrants a bug report on https://github.com/lxc/lxd/issues

You are right. In the container i get,

# udevadm info --name /dev/bus/usb/004/002
P: /devices/pci0000:00/0000:00:14.0/usb4/4-10
N: bus/usb/004/002
E: BUSNUM=004
E: DEVNAME=/dev/bus/usb/004/002
E: DEVNUM=002
E: DEVPATH=/devices/pci0000:00/0000:00:14.0/usb4/4-10
E: DEVTYPE=usb_device
E: DRIVER=usb
E: MAJOR=189
E: MINOR=385
E: PRODUCT=45e/76d/103
E: SUBSYSTEM=usb
E: TYPE=239/2/1

while on the host i get much more information (container is running),

# udevadm info --name /dev/bus/usb/004/002 
P: /devices/pci0000:00/0000:00:14.0/usb4/4-10
N: bus/usb/004/002
E: BUSNUM=004
E: DEVNAME=/dev/bus/usb/004/002
E: DEVNUM=002
E: DEVPATH=/devices/pci0000:00/0000:00:14.0/usb4/4-10
E: DEVTYPE=usb_device
E: DRIVER=usb
E: ID_BUS=usb
E: ID_MODEL=Microsoft®_LifeCam_HD-5000
E: ID_MODEL_ENC=Microsoft®\x20LifeCam\x20HD-5000
E: ID_MODEL_FROM_DATABASE=LifeCam HD-5000
E: ID_MODEL_ID=076d
E: ID_REVISION=0103
E: ID_SERIAL=Microsoft_Microsoft®_LifeCam_HD-5000
E: ID_USB_INTERFACES=:0e0100:0e0200:010100:010200:
E: ID_VENDOR=Microsoft
E: ID_VENDOR_ENC=Microsoft
E: ID_VENDOR_FROM_DATABASE=Microsoft Corp.
E: ID_VENDOR_ID=045e
E: MAJOR=189
E: MINOR=385
E: PRODUCT=45e/76d/103
E: SUBSYSTEM=usb
E: TYPE=239/2/1
E: USEC_INITIALIZED=6635511

Is it possible to downgrade from 3.2 to 3.1?

Issue filed.

You can easily downgrade to any version that you see in the output of the command

snap info lxd

Currently it shows 3.0.1 and 3.2, but no 3.1 because it was an intermediate version.

Run snap list --all lxd to show you the locally downloaded revisions. For me I have three 3.2 revisions only.

There is also a snap download command that you can specify a specific revision to download. But the --revision= option is for the snap package developer only.