Проброс USB-принтера в контейнер LXD

Хочу поделиться найденным решением по пробросу принтера HP LaserJet 1000 в контейнер, созданый при помощи LXD.

Немного предыстории


Есть домашний сервер на базе старого ноутбука Acer Aspire 5520G, который используется для всяких экспериментов. На нем была установлена Ubuntu 14.04 и создано несколько контейнеров при помощи LXC, один из которых использовался как принт-сервер.

Проброс принтера был осуществлен путем добавления в файл конфигурации гостя следующих строк:

lxc.cgroup.devices.allow = c 189:* rwm
lxc.mount.entry = /dev/bus/usb/003 dev/bus/usb/003 none bind,optional,create=dir
lxc.mount.entry = /dev/usb/lp0 dev/usb/lp0 none bind,optional,create=file

Все работало отлично, но захотелось обновиться до Ubuntu 16.04 и попробовать LXD.

Оказалось, что старые файлы конфигурации не работают и нужно искать новое решение. Вот им-то и хочу поделиться.

Приступаем к пробросу


Итак, Ubuntu 16.04+LXD установлены, контейнер на базе той же Ubuntu 16.04 создан, приступаем к пробросу.
Для начала выясним, куда подключен принтер на хосте:

root@aspire-5520g:~# lsusb
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 004 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 001 Device 004: ID 0bda:8197 Realtek Semiconductor Corp. RTL8187B Wireless Adapter
Bus 001 Device 003: ID 5986:0102 Acer, Inc Crystal Eye Webcam
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 003 Device 002: ID 03f0:0517 Hewlett-Packard LaserJet 1000
Bus 003 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub

Принтер подключен на Bus 003 Device 002, другими словами, ему соответствует unix-char файл /dev/bus/usb/003/002
Выясним, кто является его владельцем и с какими правами:

root@aspire-5520g:~# ls -l /dev/bus/usb/003/002
crw-rw-r-- 1 root lp 189, 257 Июл 15 16:02 /dev/bus/usb/003/002

Файл принадлежит пользователю root и группе lp, права на файл 0664. Данная информация пригодится нам в будущем.
Выясним, какой числовой идентификатор у группы lp:

root@aspire-5520g:~# cat /etc/group | egrep lp
lp:x:7:

Группа lp имеет числовой идентификатор 7.
Теперь выясним, кто является владельцем и с какими правами, файла lp0:

root@aspire-5520g:~# ls -l /dev/usb/lp0
crw-rw---- 1 root lp 180, 0 Июл 15 16:02 /dev/usb/lp0

Файл принадлежит пользователю root и группе lp с правами 0660.

К сожалению, отвязаться от шины USB способом под спойлером не получилось.
Поиски продолжаются…
Оставлю для истории:
UPD 07/03/2017
UPD 07/03/2017 Перед пробросом, применим хитрость в виде привязки устройстройств при помощи udev.
В моем случае принтер подключен один, поэтому привязку произвожу удобным для меня способом. Если захотите проделать подобное на своей системе, имейте ввиду, что у вас все может быть немного по-другому, но, как говориться, главное уловить суть.

Для осуществления проброса в независимости от шины подключения, на хостовой машине (не в контейнере!) создадим файл: /etc/udev/rules.d/10-printer.rules следующего содержания:

10-printer.rules
SUBSYSTEM=="usb", ATTR{manufacturer}=="Hewlett-Packard", ATTR{product}=="hp LaserJet 1000", SYMLINK+="lj1000"
KERNEL=="lp[0-9]", SUBSYSTEM=="usbmisc", SYMLINK+="%k"


Помните, что udev не поддерживает переноса строк ни в какой форме. Не допускайте разрыва строк в ваших правилах, так как udev интерпретирует ваше одно правило как несколько правил, и не будет работать как ожидалось.
(За более детальной информацией по написанию правил udev рекомендую обратиться сюда или к оригиналу сюда)

Данное правило позволяет создать две символьные ссылки lj1000 и lp0, необходимые для дальнейшего корректного проброса принтера в контейнер и нормальной его работы в независимости от шины подключения на хостовой системе.


Пробросим принтер в контейнер


На самом деле, все оказалось не сильно и сложно. В моем случае контейнер называется print, а устройство я решил назвать lj1000. Для проброса нужно выполнить несколько простых манипуляций:

root@aspire-5520g:~# lxc config device add print lj1000 unix-char path=/dev/bus/usb/003/002 mode=0664 gid=7
Устройство lj1000 добавляется к print
root@aspire-5520g:~# lxc config device add print lp0 unix-char path=/dev/usb/lp0 gid=7
Устройство lp0 добавляется к print

UPD 07/03/2017
root@aspire-5520g:~# lxc config device add print lj1000 unix-char path=/dev/lj1000 mode=0664 gid=7
Устройство lj1000 добавляется к print
root@aspire-5520g:~# lxc config device add print lp0 unix-char path=/dev/lp0 gid=7
Устройство lp0 добавляется к print


Первая команда осуществляет проброс unix-char устройства с правами 0664 и принадлежащего группе 7 (lp), вторая команда осуществляет проброс устройства lp0 с правами по умолчанию (0660) и принадлежащего той же группе 7.

Вот и все. Проброс устройства осуществлен. Далее необходимо установить принтер в контейнере:

root@aspire-5520g:~# lxc exec print -- apt update && apt upgrade -y && apt install hplip -y
root@aspire-5520g:~# lxc exec print -- hp-setup -i

Здесь просто следуем инструкции установщика. Результатом должна стать распечатанная пробная страница печати.

Вот и все, вот таким способом пробрасывается принтер внутрь контейнера созданного при помощи LXD. Думаю, что любое другое устройство пробрасывается подобным способом.

Всем спасибо за внимание.

UPD: 09/03/2017 К сожалению все оказалось не так просто и описанные правила udev не дают отвязаться от шины USB. Поиски продолжаются…
UPD: 07/03/2017 В коментариях возник вопрос по поводу привязки устройства к шине USB, с целью не потерять принтер в случае, если его случайно или умышленно переподключат в другой разъем или переподключат по питанию. Чесно скажу, для меня этот вопрос стал очен актуальным, поэтому я решил дополнить статью дополнительными инструкциями, которые позволят данной неприятности избежать, а также поправлю комманды в самой статье, чтобы не переписывать все заново.

Similar posts

AdBlock has stolen the banner, but banners are not teeth — they will be back

More
Ads

Comments 15

    0
    Адреса устройств USB могут меняться при включении даже в тот же самый порт. Как Вы решаете эту проблему?

    Замечу также, что команда
    getent group lp
    

    предпочтительнее, чем
    cat /etc/group | egrep lp
    
    , так как оперирует NSS, а не только файлами и делает в точности то, что нужно
      +1
      Но стоит помнить, что getent входит в libc-bin, которая может быть не всюду установлена. В том же контейнере её может не быть
        0
        Адреса устройств меняются только в том случае, если вы пытаетесь переключить устройство в другой порт, или переподключить в тот же порт с малым промежутком времени. При переподключении в тот же порт с малым промежутком времени, можно написать правило в udev, закрепив принтер по серийному номеру.
        При перезагрузке ни разу не наблюдал, чтобы устройство, которое подключено к одному и тому же порту меняло адрес. (Эксплуатирую данное решение не долго, но до этого, как и описывал, эксплуатировал решение на Ubuntu 14.04 и LXC 1.0, проблем не замечено)
          0
          адреса назначаются по порядку, и если устройство задумается с ответом, у него может быть другой адрес :)
          Попробуйте, например
          lsusb -d 9710:7830 | tr ':' ' ' | cut -d ' ' -f 2,4
            0
            Ну я в принципе тоже и написал. При быстром переподключении может смениться адрес, но это можно решить при помощи udev.
              0
              А я говорю про первую загрузку. Я бы не стал полагаться на то, что устройство всегда получит адрес A на шине B.
              И да, правило в udev поможет.
                0
                Не совсем понял, про первую загрузку.
                Если про первую загрузку контейнера, то в любом случае устройство пробрасывается из хоста, а значит перед тем, как пробросить устройство, оно должно уже быть подключено к хосту, иначе это будет не проброс конкретного устройства, а проброс шины в целом, т.к. адрес конкретного устройства определить попросту не получится.
        0
        А может кто разбирался почему в контейнерах не работают kernel логи?
          0
          Наверное потому что контейнер использует kernel хоста?
            0
            Там их тоже нет.
          0
          У меня модем как-то так проброшен
          lxc.cgroup.devices.allow = c 188:0 rwm
          lxc.autodev: 1
          lxc.hook.autodev: sh -c «mknod -m 0666 ${LXC_ROOTFS_MOUNT}/dev/ttyUSB0 c 188 0»
          
            0
            А какая версия lxc при этом используется? У меня в старой версии до 2.0 тоже так работало, ну или похожим образом.
              0
              2.0.7
                0
                Ну и как? Работает такое в LXD?
                Кстати, еще полезно бывает «передернуть» USB на хосте чем-то вроде
                echo -n "0000:00:1d.0" | tee /sys/bus/pci/drivers/ehci-pci/unbind && echo -n "0000:00:1d.0" | tee /sys/bus/pci/drivers/ehci-pci/bind

                Рецепт «передергивания» для USB2.0 и 3.0
                  0

                  В ответ на предыдущий комментарий ничего не скажу. Пока отложил lxd в связи с недоступностью стенда, да и к тому же перешёл на proxmox, а вот за рецепт передергивания устройства большое спасибо. Попробую на сервере, для меня программное передергивание устройств очень наболевшая и актуальная тема

            Only users with full accounts can post comments. Log in, please.