В статье Стефана Грабера (Stéphane Graber) речь пойдёт о возможности пробросить USB устройства хоста внутрь контейнера, что, в некоторых случаях, позволит не захламлять свою основную систему.
Иногда необходимо пробросить USB внутрь контейнера. Возможно это измерительное устройство в лаборатории или телефон Android или даже устройство из мира IoT, с которым вам нужно взаимодействовать.
Подобно тому что было описано в статье про прокидывание GPU внутрь контейнера, LXD также поддерживает проброс USB. Опять же, как и в случае с GPU, фактически в контейнер передаётся уже готовое символьное устройство UNIX, в нашем случае /dev/bus/usb/<device-node>
Это ограничивает USB passthrough теми устройствами и программами, которые используют libusb для взаимодействия. Для устройств, которые используют модуль ядра (kernel driver), то он должен быть установлен и загружен на хост-системе, а результирующее устройство нужно прокинуть в контейнер напрямую. Обратите внимание, что для работы нам понадобится LXD 2.5 или выше.
В качестве примера, с которым может столкнуться много людей, можно запустить контейнер, с установленным инструментарием для Андроид, и получить доступ к подключённому телефону. Это, например, позволит вам внутри контейнера создать систему сборки и непрерывной интеграции (Continuous Integration, CI), которые будут взаимодействовать с одним или несколькими подключёнными через USB устройствами. Сначала перед подключением к USB убедитесь, что телефон разблокирован и в нём включена отладка по USB.
В хост-системе вы должны наблюдать что-то типа
lsusb
Bus 002 Device 003: ID 0451:8041 Texas Instruments, Inc. Bus 002 Device 002: ID 0451:8041 Texas Instruments, Inc. Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub Bus 001 Device 021: ID 17ef:6047 Lenovo Bus 001 Device 031: ID 046d:082d Logitech, Inc. HD Pro Webcam C920 Bus 001 Device 004: ID 0451:8043 Texas Instruments, Inc. Bus 001 Device 005: ID 046d:0a01 Logitech, Inc. USB Headset Bus 001 Device 033: ID 0fce:51da Sony Ericsson Mobile Communications AB Bus 001 Device 003: ID 0451:8043 Texas Instruments, Inc. Bus 001 Device 002: ID 072f:90cc Advanced Card Systems, Ltd ACR38 SmartCard Reader Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
В данном примере нужное это Sony Ericsson Mobile. Теперь создаём контейнер - lxc launch ubuntu:16.04 c1
Creating c1 Starting c1
Нужно установить инструментарий Андроид для отладки - lxc exec c1 -- apt install android-tools-adb
Пробуем получить список подключённых Андроид устройств внутри контейнера - lxc exec c1 -- adb devices
* daemon not running. starting it now on port 5037 * * daemon started successfully * List of devices attached
Мы ничего ещё не пробрасывали внутрь контейнера и поэтому список ожидаемо пустой.
Давайте пробросим телефон из вывода lsusb - lxc config device add c1 sony usb vendorid=0fce productid=51da
Device sony added to c1
Снова просим список устройств внутри контейнера - lxc exec c1 -- adb devices
* daemon not running. starting it now on port 5037 * * daemon started successfully * List of devices attached CB5A28TSU6 device
Для получения shell можно использовать lxc exec c1 -- adb shell
* daemon not running. starting it now on port 5037 * * daemon started successfully * E5823:/ $
LXD поддерживает по умолчанию режим горячего подключения (hotplug) для устройств USB. Вы можете вынимать устройство и снова его подключать к хосту, что приведёт к удалению и добавлению снова в контейнер. Свойство productid не обязательно, вы можете использовать только vendorid и все устройства данного производителя будут подключены автоматически. Это удобно в случаях, когда есть много подобных устройств или для устройств, которые меняют productid в зависимости от режима, в котором работают.
lxc config device remove c1 sony
Device sony removed from c1
lxc config device add c1 sony usb vendorid=0fce
Device sony added to c1
lxc exec c1 -- adb devices
* daemon not running. starting it now on port 5037 * * daemon started successfully * List of devices attached CB5A28TSU6 device
Опциональное свойство required выключает поведение hotplug. Теперь перед стартом контейнера устройство должно присутствовать.
Ключ | Тип | По умолч. | Требуется | Описание |
---|---|---|---|---|
vendorid | string | - | да | id производителя USB устройства |
productid | string | - | нет | id продукта USB устройства |
uid | int | 0 | no | UID владельца устройства в контейнере |
gid | int | 0 | нет | GID владельца устройства в контейнере |
mode | int | 0660 | нет | права доступа к устройству внутри контейнера |
required | boolean | false | нет | Требуется ли это устройство для запуска контейнера. По умолчанию нет и все устройства подразумеваются как hot-pluggable |
Мы окружены множеством несчётных USB устройств, часть которых требует через своё изворотливое ПО конкретную версию конкретного дистрибутива Linux. Трудно выполнить все эти условия, сохранив свою основную систему в чистоте и безопасности.
Проброс USB с помощью LXD поможет в этом случае, если используется libusb и не требуется какой-то специфичный модуль ядра (kernel driver).
Если вы хотите добавить устройство, которое использует модуль ядра, то найдите устройство в /dev/. Проверьте символьное или блочное оно и передайте его LXD в качестве устройства как unix-char или unix-block.
Цикл из 12 статей Стефана про LXD.
Из свежего про LXD и LXC, который работает под капотом.