Senior Linux Administrator
0,5
рейтинг
20 августа 2015 в 11:55

Администрирование → Проброс USB в виртуалку по сети средствами UsbRedir и QEMU tutorial



На сегодняшний день существет довольно много способов пробросить USB-устройство на другой компьютер или виртуалку по сети.
Из наиболее популярных — железячные такие как AnywhereUSB и чисто програмные продукты, из тех что я попробовал сам: USB Redirector и USB/IP.
Я бы хотел рассказать вам еще об одном интересном способе, который работает непосредственно с эмулятором QEMU.
Он так же является частью проекта spice, официально поддерживаемым RedHat.

UsbRedir, это открытый протокол для проброса usb-устройств по tcp на удаленный виртуальный сервер, разработанный при поддержке RedHat в рамках проекта spice. Но как оказалось им можно вполне успешно пользоваться и без spice. В роли сервера выступает usbredirserver, который шарит usb-устройство на определенный порт, а в качестве клиента сам QEMU, который эмулирует подключение экспортированного usb-устройства в определенный usb-контроллер вашей виртуальной машины. Благодаря такому подходу в качестве гостевой системы может использоваться абсолютно любая ОС, так как она даже не знает, что устройство является проброшенным удаленно, а вся логика ложится на QEMU.

Для начала несколько слов о вышеперчисленных решениях


  • AnywhereUSB — довольно неплохое решение, но дорогое, и имеет неприятние глюки, например бывает если расшаренная флешка отваливается, то переподключить ее обратно можно только физически вынув и вставив ее.
  • USB/IP — OpenSource проект. Вроде как был заброшен. По факту глючит довольно сильно. При разрыве соединения, машина частенько уходит в полнейший freezee, а windows показывает BSOD
  • USB Redirector — Замечательная софтина. Для расшаривания устройств с linux на linux бесплатна, во всех остальных случаях уже стоит денег, не так много как AnywhereUSB, но и не бесплатно как хотелось бы :)

Как видно есть из чего выбрать, но давайте же наконец попробуем еще один способ — UsbRedir?

Настройка виртуальной машины



Для того что бы было куда подключать экспортированные устройства, на виртуальной машине нужно создать необходимые usb-контроллеры:
  • uhci — для USB1.0
  • ehci — для USB2.0
  • xhci — для USB3.0

Для qemu (без libvirt)


Добавьте опции в команду запуска виртуальной машины:
-device ich9-usb-ehci1,id=ehci,addr=1d.7,multifunction=on
-device ich9-usb-uhci1,id=uhci-1,addr=1d.0,multifunction=on,masterbus=ehci.0,firstport=0
-device ich9-usb-uhci2,id=uhci-2,addr=1d.1,multifunction=on,masterbus=ehci.0,firstport=2
-device ich9-usb-uhci3,id=uhci-3,addr=1d.2,multifunction=on,masterbus=ehci.0,firstport=4


Для libvirt

В исходном файле конфигурации виртуальной машины в узле <devices> удаляем все USB контроллеры и добавляем следущий блок:
<controller type='usb' index='0' model='ich9-ehci1'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x08' function='0x7'/>
</controller>
<controller type='usb' index='0' model='ich9-uhci1'>
<master startport='0'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x08' function='0x0' multifunction='on'/>
</controller>
<controller type='usb' index='0' model='ich9-uhci2'>
<master startport='2'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x08' function='0x1'/>
</controller>
<controller type='usb' index='0' model='ich9-uhci3'>
<master startport='4'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x08' function='0x2'/>
</controller>


Кстати, если вы используете spice, то добавив к контроллерам еще 3 специальных девайса, станет возможен проброс usb-устройств с клиента spice на сервер.
Пример под спойлером
Для qemu

Добавляем следующие опции в команду запуска виртуальной машины, помимо контроллеров определеных нами раньше:
-chardev spicevmc,name=usbredir,id=usbredirchardev1
-device usb-redir,chardev=usbredirchardev1,id=usbredirdev1,debug=3
-chardev spicevmc,name=usbredir,id=usbredirchardev2
-device usb-redir,chardev=usbredirchardev2,id=usbredirdev2,debug=3
-chardev spicevmc,name=usbredir,id=usbredirchardev3
-device usb-redir,chardev=usbredirchardev3,id=usbredirdev3,debug=3


Для libvirt

В исходном файле конфигурации виртуальной машины в узле <devices> добавляем следующие опции, помимо контроллеров определеных нами раньше:
<redirdev bus='usb' type='spicevmc'><address type='usb' bus='0' port='3'/></redirdev>
<redirdev bus='usb' type='spicevmc'><address type='usb' bus='0' port='4'/></redirdev>
<redirdev bus='usb' type='spicevmc'><address type='usb' bus='0' port='5'/></redirdev>
<redirdev bus='usb' type='spicevmc'><address type='usb' bus='0' port='6'/></redirdev>



Теперь все готово для осуществления проброса.

Запуск сервера


Пакет usbredirserver можно найти в стандартных репозиториях практически во всех популярных дистрибутивах linux.

Вставляем флешку в компьютер, смотрим вывод usb-устройств:
$ lsusb
...
Bus 003 Device 011: ID 125f:c82a A-DATA Technology Co., Ltd. 
...


Видим что пара vendorid:prodid равна 125f:c82a, а ядро определило флешке 003-001 usbbus-usbaddr соотвественно.

Теперь давайте расшарим ее на 4000 порт:

# Используя пару vendorid:prodid
$ usbredirserver -p 4000 125f:c82a
# Используя пару usbbus-usbaddr
$ usbredirserver -p 4000 003-011


Подключение устройства к виртуальной машине



Через опции при запуске ВМ



Устройство которое нужно подключить к ВМ можно указать при запуске, добавив следующие опции в команду запуска

Для qemu

-chardev socket,id=usbredirchardev1,port=4000,host=192.168.1.123
-device usb-redir,chardev=usbredirchardev1,id=usbredirdev1,bus=ehci.0,debug=4


Для libvirt

Этот блок рамещается перед тегом </devices>, рядом с контроллерами определенными нами раньше:
<redirdev bus='usb' type='tcp'>
  <source mode='connect' host='192.168.1.123' service='4000'/>
</redirdev>
Его так же можно исполнить командой virsh attach-device

Или через qemu-monitor


Заходим на гипервизор и в qemu-monitor нашей машины выполняем следующие команды:
# Добавляем наше устройство
chardev-add socket,id=usbredirchardev1,port=4000,host=192.168.1.123
# Подключем его в ehci контроллер (USB-2.0)
device_add usb-redir,chardev=usbredirchardev1,id=usbredirdev1,bus=ehci.0,debug=4

Что бы отключить флешку достаточно такой команды:
device_del usbredirdev1


На этом все, после данных шагов ваша ВМ увидит вашу флешку и сможет с ней нативно работать.

Если устройств много и все они одинаковые


Вот тут появилась интересная задачка, как пробросить несколько одинаковых девайсов на разные ВМ?
При этом, стоит отметить, все устройства имеют одинаковую пару vendorid:prodid, а пара usbbus-usbaddr совсем не постоянна, стоит только вынуть и вставить устройство, так оно сразу поменяет свой usbaddr.

Я решил ее при помощи udev.
Кстати если вы не совсем понимаете как работает udev, на Debian Wiki есть классная статья о udev

И так приступим


Для начала нам надо узнать серийник нашего устройства, по которому и будем идентифицировать его в udev:

Запустим udev-монитор:
$ udevadm monitor --environment --udev

И вставим наше устройство, после этого мы сразу увидим список переменных этого устройства которые udev любезно инициализировал для нас:
...
UDEV  [189056.151508] add      /devices/virtual/bdi/8:16 (bdi)
ACTION=add
DEVPATH=/devices/virtual/bdi/8:16
ID_SERIAL_SHORT=11C130317234004B
SEQNUM=4352
SUBSYSTEM=bdi
USEC_INITIALIZED=189056149826
...

Информацию о серийнике и других аттрибутах можно получить и другим способом, но стоит учитывать что для написания правил мы будем использовать именно переменные из команды выше, а не аттрибуты из команды ниже. В противном случае не будет отрабатывать триггер remove при отключении устройства.
$ udevadm info -a -n /dev/bus/usb/003/011 | grep '{serial}'


Теперь создадаим файл /etc/udev/rules.d/99-usb-serial.rules и запишем в него следующие правила:
ACTION=="add", ENV{ID_SERIAL_SHORT}="11C130317234004B", RUN+="/usr/bin/usbredirserver -p 4000 $attr{busnum}-$attr{devnum}"
ACTION=="remove", ENV{ID_SERIAL_SHORT}="11C130317234004B", RUN+="/usr/bin/fuser -k 4000/tcp"


Перезагрузим udev-правила:
$ udevadm control --reload-rules

Готово, теперь при подключении нашего устройства, оно будет автоматически шарится на нужный нам порт, а при отключении usbredirserver будет прекращать свою работу.
По аналогии добавляем и остальные устройства.

На этом все. Спасибо за проявленный интерес :)

UPD: Тем кому интересно, что из этого в итоге получилось, можете посмотреть здесь



Источники:


umvirt.ru/node/82
opennebula.org/opennebula-for-virtual-desktops
opennet.ru/opennews/art.shtml?num=30773
lists.gnu.org/archive/html/qemu-devel/2013-07/msg05244.html
askubuntu.com/questions/49910/how-to-distinguish-between-identical-usb-to-serial-adapters
bugzilla.redhat.com/show_bug.cgi?id=805172#c26
kvaps @kvaps
карма
50,0
рейтинг 0,5
Senior Linux Administrator
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Администрирование

Комментарии (21)

  • 0
    Можно ли пробросить с помощью данной методики Sentinel HL на HyperV под управлением Windows Server 2012?
    • 0
      Неа, работает только в связке с qemu
      • 0
        Можно, если на Windows поставить клиент и подключаться по сети к серверу. Но такая связка уже денег стоит
        • 0
          Какой клиент?
          • 0
            ответил в личку
        • 0
          Вы точно не путаете UsbRedir с USB Redirector?
          • 0
            Да, точно, я USB Redirector имел в виду
  • 0
    Как считаете, возможно-ли пробросить таким образом USB2COM? Или подобные хитрые железки?
    • 0
      Думаю что пробросить можно пробросить любое usb-устройство, которое определится и появится в /dev/bus/usb
      • 0
        Я пришёл к выводу, что пробросить то можно всё что угодно… А вот реально работать может ДАЛЕКО, ДАЛЕКО не всё… То ли команды USB не все пробрасываются, или чего ещё… Пробовал в своё время: USB/IP — не работало. Пробовал пробрасывать через настройки ESXi — не заработало.

        В любом случае, спасибо за статью. Надо попробовать. Но если у Вас будет возможность пробросить что-то специфическое — будет здорово. Есть же всякие, видеокарты USB, видеотюнеры… — Но я предлагаю, Вам попробовать пробросить USB видеокамеру… — По-моему отличный тест будет!
        • 0
          Я уже пробрасывал встроенную в ноутбук камеру таким образом, вот вам пара скриншотов для подтверждения
          • 0
            Выглядит обнадёживающе… Хочу пробросить таким образом USB2COM, чтобы считывать показания с древних электроустановок на работе.
  • 0
    Не совсем понимаю зачем такой огород городить, если устройство можно просто воткнуть в usb порт на хосте и пробросить в виртуалку штатными средствами qemu.
    • +1
      В данной статье хотелось описать именно удаленный проброс usb, то есть с одного компьютера на гипервизор, а не в пределах одного гипервизора.

      Кстати, как было сказано выше в статье, после подобной настроки qemu, станет возможен проброс usb по протоколу spice простым пользователям через virt-viewer
      • 0
        Ну если так, то и тут есть куча более простых решений, навскидку сразу USB-over-Network. Клиент-серверная фигня, причём позволяет пробросить что угодно куда угодно, главное, что бы были USB.

        PS к тому же кроссплатформенная, и когда последний раз смотрел была ещё и бесплатная)
  • 0
    Нужно пробросить HASP в виртуалку на Proxmox 3.4
    ОС в виртуалке — Win2012 R2

    Делаю всё по вашей инструкции, устройства пробрасываются, но в Windows возникает ошибка USB\DEVICE_DESCRIPTOR_FAILURE

    Пробовал также другие USB-устройства (флешка, сетевушка и пр.) — результат тот же.
    Подскажите, в чём может быть проблема?
    • 0
      HASP воткнут в хостовую машину непосредственно? Если да, не городите велосипед, воспользуйтесь штатными средствами Proxmox. В сети куча материала на эту тему, например вот и вот

      И никакого лишнего софта (а значит и точек отказа) в целевой ОС, всё делается исключительно средствами гипервизора.
      • 0
        Нет, HASP не в хостовой машине.
        Хост находится в удалённом дата-центре, физического доступа к нему нет и не предвидится. Именно поэтому и стоит задача пробрасывать USB-устройства с локальной машины.
        • 0
          Ну тогда самый дешевый по трудозатратам вариант USB over Network или что-то типа того, хотя не могу отрицать — сабж будет феншуйнее
        • 0
          Посмотрите мой репозиторий, там описанно уже готовое решение на основе usbredir, как раз для proxmox.
          Работает более чем стабильно.

          По ошибке: usb-контроллеры создали? У меня было что-то похожее когда я пытался устройства в USB1.0 хаб воткнуть (виртуальный в смысле)
  • 0

    Хочется заменить, что донглы Alladin HASP всё-таки таким способом пробросить не удастся. А именно, если их более одного, вы не сможете их различить, ведь у них нет серийного номера (в дескрипторе USB идентификатор строки с серийным номером равен нулю):


    [    2.765027] usb 3-12: New USB device found, idVendor=0529, idProduct=0001
    [    2.765032] usb 3-12: New USB device strings: Mfr=1, Product=2, SerialNumber=0
    [    2.765035] usb 3-12: Product: HASP 2.17
    [    2.765038] usb 3-12: Manufacturer: AKS
    

    Нужно какое-то решение, которое позволит надёжно различать их именно по физическому порту, в который вставлен донгл, например, железка со структурой "по одному порту на один USB-котроллер". Любые другие решения, увы, неработоспособны.

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.