UsbRedirとQEMUを使用してUSBをネットワーク経由で仮想マシンに転送する



今日、USBデバイスをネットワーク経由で別のコンピューターまたは仮想マシンに転送する方法はかなりあります。
最も人気のあるハードウェア-AnywhereUSBなどのハードウェア、および純粋にソフトウェア製品、私が試したものの中で:USBリダイレクタとUSB / IP。
QEMUエミュレーターで直接機能する別の興味深い方法についてお話ししたいと思います。
また、RedHatによって公式にサポートされているスパイスプロジェクトの一部です。

UsbRedirは、spcpプロジェクトの一部としてRedHatサポートで開発されたリモート仮想サーバーにtcpを介してusbデバイスを転送するためのオープンプロトコルです。 しかし、判明したように、スパイスなしで非常にうまく使用できます。 Usbredirserverは、usbデバイスを特定のポートに移動するサーバーとして機能し、QEMU自体はクライアントとして機能し、エクスポートされたusbデバイスの仮想マシンの特定のusbコントローラーへの接続をエミュレートします。 このアプローチのおかげで、デバイスがリモートで配線されていることすらわからず、すべてのロジックがQEMUにあるため、すべてのOSをゲストシステムとして使用できます。

最初に、上記のソリューションに関するいくつかの言葉



どうやら選択することがたくさんありますが、最終的に別の方法を試してみましょう-UsbRedir?

仮想マシンのセットアップ



エクスポートされたデバイスを仮想マシンに接続するには、必要なusbコントローラーを作成する必要があります。

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フラッシュドライブをコンピューターに挿入し、USBデバイスの出力を確認します。
 $ lsusb ... Bus 003 Device 011: ID 125f:c82a A-DATA Technology Co., Ltd. ... 


vendorid:prodidのペアは125f:c82aに等しく、カーネルはそれぞれUSBフラッシュドライブ003-001 usbbus-usbaddrを定義したことがわかります。

次に、ポート4000で共有しましょう。

 #   vendorid:prodid $ usbredirserver -p 4000 125f:c82a #   usbbus-usbaddr $ usbredirserver -p 4000 003-011 


デバイスを仮想マシンに接続する



VMの起動時のオプション経由



VMに接続するデバイスは、起動コマンドに次のオプションを追加することにより、起動時に指定できます

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 


以上が、これらの手順の後、VMにフラッシュドライブが表示され、ネイティブでそれを操作できるようになります。

多数のデバイスがあり、それらがすべて同じ場合


ここで、興味深い問題が発生しました。複数の同一のデバイスを異なるVMに転送する方法ですか?
同時に、すべてのデバイスが同じ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 ... 

シリアルおよびその他の属性に関する情報は別の方法で取得できますが、ルールを記述するために、以下のコマンドの属性ではなく、上記のコマンドの変数を使用することを検討する価値があります。 そうしないと、デバイスがオフになったときに削除トリガーが機能しません。
 $ 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

Source: https://habr.com/ru/post/J265065/


All Articles