「QEMU」の版間の差分

提供: ArchWiki
ナビゲーションに移動 検索に移動
(→‎Keyboard issues when using VNC: https://wiki.archlinux.org/index.php?title=QEMU&oldid=745549 (2022-09-10T19:23:13) をインポート)
(→‎Could not read keymap file: https://wiki.archlinux.org/index.php?title=QEMU&oldid=745549 (2022-09-10T19:23:13) をインポート)
1,757行目: 1,757行目:
 
キーの一部が動かなかったり間違ったキーが押されてしまう (特に矢印キー) ときは、おそらくキーボードレイアウトをオプションとして指定する必要があります。キーボードレイアウトは {{ic|/usr/share/qemu/keymaps}} で探すことができます。
 
キーの一部が動かなかったり間違ったキーが押されてしまう (特に矢印キー) ときは、おそらくキーボードレイアウトをオプションとして指定する必要があります。キーボードレイアウトは {{ic|/usr/share/qemu/keymaps}} で探すことができます。
 
$ qemu-system-x86_64 -k ''keymap'' ''disk_image''
 
$ qemu-system-x86_64 -k ''keymap'' ''disk_image''
  +
  +
=== Could not read keymap file ===
  +
  +
qemu-system-x86_64: -display vnc=0.0.0.0:0: could not read keymap file: 'en'
  +
  +
is caused by an invalid ''keymap'' passed to the {{ic|-k}} argument. For example, {{ic|en}} is invalid, but {{ic|en-us}} is valid - see {{ic|/usr/share/qemu/keymaps/}}.
   
 
=== ウィンドウのリサイズでゲストのディスプレイが引き伸ばされる ===
 
=== ウィンドウのリサイズでゲストのディスプレイが引き伸ばされる ===

2022年9月11日 (日) 13:56時点における版

関連記事

QEMU ホームページ より:

QEMU は汎用なオープンソースのマシンエミュレータ・バーチャライザーです。

マシンエミュレータとして使う場合、QEMU はあるマシン (例: ARM ボード) 用に作られた OS やプログラムを他のマシン (例: x86 PC) で動かすことができます。動的変換を利用することによって、素晴らしいパフォーマンスを実現します。

XenKVM など他のハイパーバイザを使うことで QEMU は仮想化のための CPU 拡張命令を利用することができます。バーチャライザーとして使う場合、ゲストコードをホスト CPU で直接実行することにより QEMU はネイティブに近いパフォーマンスを得ることができます。

目次

インストール

qemu-full パッケージ (または GUI が必要ない場合は qemu-base) をインストールしてください。また、任意で以下のパッケージもインストールしてください:

あるいは、ユーザーモードと静的のバリアントとして qemu-user-staticAUR が存在します。

QEMU バリアンツ

QEMUには、さまざまなユースケースに適したいくつかのバリアンツが用意されています。

最初の分類として、QEMUにはフルシステムエミュレーションモードとユーザーモードエミュレーションモードの2種類が提供されています。

フルシステムエミュレーション
このモードでは、QEMUは1つまたは複数のプロセッサとさまざまな周辺機器を含むフルシステムをエミュレートします。より正確ですが速度は遅く、エミュレートするOSはLinuxである必要がありません。
フルシステムエミュレーション用のQEMUコマンドは qemu-system-target_architecture という名前が付けられています。例えば インテル64ビットCPUのエミュレーション用の qemu-system-x86_64 、インテル32ビットCPU用の qemu-system-i386 、 ARM(32ビット)用の qemu-system-arm 、 ARM64用の qemu-system-aarch64 などです。
ターゲットアーキテクチャがホスト CPU と一致する場合、このモードでも KVM や Xen のようなハイパーバイザーを使うことで大幅なスピードアップの恩恵を受けられるかもしれません。
ユーザーモードエミュレーション
このモードでは、QEMUはホストシステムのリソースを利用することで、(潜在的に)異なるアーキテクチャ用にコンパイルされた Linux 実行ファイルを呼び出すことができます。互換性の問題がある場合があります。例えば、一部の機能が実装されていない、動的リンクされた実行ファイルがそのままでは動作しない(これについては#x86_64 から arm/arm64 環境への Chrootingを参照)、そして Linux のみがサポートされています(ただし Windows 実行ファイルの実行には Wine が使用できる場合があります)。
ユーザーモードエミュレーション用のQEMUコマンドには qemu-target_architecture という名前が付けられており、例えばintel 64ビットCPUのエミュレーション用は qemu-x86_64 になります。

QEMU には動的リンク型と静的リンク型のバリアンツが提供されています。

動的リンク型(デフォルト)
qemu-* コマンドはホストOSのライブラリに依存し、このため実行ファイルのサイズが小さくなっています。
静的リンク型
qemu-* コマンドは同じアーキテクチャの Linux システムにコピーすることができます。

Arch Linux の場合、フルシステムエミュレーションは以下のように提供されます:

非ヘッドレス (デフォルト)
このバリアントでは、追加の依存関係(SDL や GTK など)を必要とする GUI 機能を使用できます。
ヘッドレス
GUI を必要としないスリムなバリアントです(サーバなどに適しています)。

ヘッドレス版と非ヘッドレス版は同じ名前のコマンド(例: qemu-system-x86_64)をインストールするため、両方を同時にインストールすることはできないことに注意してください。

Arch Linux で利用可能なパッケージの詳細

  • qemu-desktop パッケージはフルシステムエミュレーション用の x86_64 アーキテクチャエミュレータを提供します(qemu-system-x86_64)。 qemu-emulators-full パッケージは、x86_64 ユーザモード版 (qemu-x86_64) を提供し、サポートされている他のアーキテクチャについても、フルシステム版と ユーザモード版の両方(例: qemu-system-arm および qemu-arm )が含まれています。
  • これらのパッケージのヘッドレスバージョン (フルシステムエミュレーションにのみ適用可能) は、 qemu-base (x86_64-のみ) および qemu-emulators-full (その他のアーキテクチャ) です。
  • フルシステムエミュレーションは、別のパッケージに含まれるいくつかの QEMU モジュールを使用して拡張することができます: qemu-block-gluster, qemu-block-iscsi, qemu-block-rbd, qemu-guest-agent.
  • 非公式の AUR パッケージ qemu-user-staticAUR は QEMU がサポートする全てのターゲットアーキテクチャにユーザーモードと静的バリアントを提供します。このパッケージのプリコンパイルバージョンが存在します: qemu-user-static-binAUR 。インストールされる QEMU コマンドは qemu-target_architecture-static という名前で、例えば intel 64-bit CPU 用は qemu-x86_64-static です。
  • 非公式の AUR パッケージ qemu-loongarch64-gitAUR は(qemu-system-loongarch64-gitAURqemu-loongarch64-static-gitAUR とともに) LoongArch アーキテクチャ用の QEMU で、version 7.1 から公式にサポートされています。
ノート: 現在のところ、Arch はフルシステムモードと静的リンクのバリアントを提供していません(公式にも AUR 経由でも)。これは通常は必要ないためです。

QEMUのグラフィカルフロントエンド

VirtualBoxVMware などの他の仮想化プログラムと違って、QEMUは仮想マシンを管理するためのGUI (仮想マシン実行時に表示されるウィンドウを除く)を提供せず、保存された設定を使って永続的な仮想マシンを作成する方法も提供しません。仮想マシンを起動するためのカスタムスクリプトを作成していない限り、仮想マシンを実行するためのすべてのパラメータは、起動のたびにコマンドラインで指定する必要があります。

Libvirt は、QEMU 仮想マシンを管理するための便利な方法を提供します。利用可能なフロントエンドについては、libvirtクライアントの一覧 を参照してください。

その他の QEMU 用 GUI フロントエンド:

  • AQEMU — Qt5で書かれたQEMU GUI。
https://github.com/tobimensch/aqemu || aqemuAUR

新しい仮想化システムの作成

ヒント: Arch Linux を仮想化する場合、既存の Arch Linux システム上に直接ディスクイメージを作成することができます、詳しくはインストールガイドを見て下さい。

ハードディスクイメージの作成

ヒント: QEMU イメージに関する詳細は QEMU Wikibook を参照。

CD-ROM やネットワークからライブシステムを起動するのでない (そしてオペレーティングシステムをハードディスクイメージにインストールしない) 限り、QEMU を実行するにはハードディスクイメージが必要になります。ハードディスクイメージはエミュレートするハードディスクの内容を保存するファイルです。

ハードディスクイメージを raw にすると、ゲストからは文字通りバイト単位で等しいようになり、ホスト上のゲストハードドライブをフルに使用することになります。この方法は I/O のオーバーヘッドを最小に抑えられますが、ゲストで使用していない領域もホストは使えないため、大量の容量を消費するのが欠点です。

また、ハードディスクイメージを qcow2 などのフォーマットにすることもできます。ゲストオペレーティングシステムが実際に仮想ハードディスク上のセクタに書き込んだ時にイメージファイルに容量を割り当てます。ホストシステムで占める容量はかなり少なくて済み、ゲストオペレーションにはフルサイズのイメージとして見えます。QEMU のスナップショット機能にも対応しています (詳しくは#モニタコンソールを使ってスナップショットを作成・管理を参照)。こちらの形式では raw と違ってパフォーマンスに多少影響を与えます。

QEMU にはハードディスクイメージを作成するための qemu-img コマンドがあります。例えば raw フォーマットで 4GiB イメージを作成するには:

$ qemu-img create -f raw image_file 4G

-f qcow2 を使うことで qcow2 ディスクを作成できます。

ノート: raw イメージは ddfallocate を使って必要なサイズのファイルを作成するだけでも作れます。
警告: ハードディスクイメージを Btrfs ファイルシステム上に保存する場合、イメージを作成する前にディレクトリの Copy-on-Write を無効にするべきでしょう。

オーバーレイストレージイメージ

一度ストレージメディアを作成してから ('backing' イメージ)、QEMU にイメージへの変更を overlay イメージとして維持させることができます。これによってストレージメディアを前の状態に戻すことが可能になります。戻りたい時点で、オリジナルの backing イメージを元に新しい overlay イメージを作成することで戻すことができます。

overlay イメージを作成するには、次のようにコマンドを実行してください:

$ qemu-img create -o backing_file=img1.raw,backing_fmt=raw -f qcow2 img1.cow

その後通常通り QEMU VM を起動することができます (仮想化システムを実行するを参照):

$ qemu-system-x86_64 img1.cow

backing イメージには変更が加えられず、ストレージへの追記は overlay イメージファイルに保存されるようになります。

backing イメージのパスが変更された場合、修正が必要になります。

警告: backing イメージの絶対ファイルシステムパスは (バイナリの) overlay イメージファイルに保存されます。backing イメージのパスを変更するのは大変です。

オリジナルの backing イメージのパスからこのイメージに繋がるようにしてください。必要ならば、オリジナルのパスに新しいパスへのシンボリックリンクを作成します。次のようなコマンドを実行してください:

$ qemu-img rebase -b /new/img1.raw /new/img1.cow

あなたの判断で、backing イメージの古いパスがチェックされない'危険な' rebase を実行することもできます:

$ qemu-img rebase -u -b /new/img1.raw /new/img1.cow

イメージのリサイズ

警告: NTFS ブートファイルシステムを含んでいるイメージをリサイズするとそこにインストールされている VM が起動できなくなってしまう可能性があります。詳しい説明や回避方法は ここ を見て下さい。

qemu-img 実行可能ファイルには resize オプションがあり、ハードドライブイメージの簡単なリサイズができます。このコマンドは rawqcow2 の両方で使えます。例えば、イメージ容量を 10GB 増やすには、次を実行してください:

$ qemu-img resize disk_image +10G

ディスクイメージを拡大した後、仮想マシン内でファイルシステムおよびパーティションツールを使用して、新しいスペースを実際に使い始める必要があります。ディスクイメージを縮小する場合、仮想マシン内のファイルシステムおよびパーティションツールを使用して まず割り当てられたファイル・システムとパーティション・サイズを縮小 し、それに応じてディスクイメージを縮小する必要があります。Windows ゲストの場合、"ハードディスクパーティションの作成とフォーマット" コントロールパネルを開きます。

ヒント: NTFS ブートファイルシステムを含んでいるイメージをリサイズする方法 (この例では qcow2 フォーマットのイメージを使っていますが他のフォーマットでも方法は同じです):

重要: イメージを使用している VM はあらかじめ全てシャットダウンしてください。

リサイズするのに qcow2 から raw にイメージを変換する必要はありません (ただしイメージが NTFS で VM ゲストをそこから起動している場合は別です)。直接 qemu-img resize コマンドを使って下さい。その後、ゲストの仮想マシンを起動してディスクに新しい場所を再配置してください。

そして適当なツールを使ってパーティションのサイズを変更 (例えば Windows Vista 以降なら、Windows を起動して初めから入っている Disk Management ユーティリティ を使うことができます)。

イメージが起動する NTFS の場合、qcow2 ファイルを以下のようにして変換する必要があります:

イメージを raw フォーマットに変換して末尾に空きスペースを追加します (オリジナルのイメージはバックアップとして残しておく):

$ qemu-img convert -f qcow2 -O raw myimg.qcow2 myimg.raw
$ truncate -s +4G myimg.raw
$ mv myimg.qcow2 myimg.qcow2.bak

大きくしたイメージを qcow2 に戻して、raw は削除:

$ qemu-img convert -f raw -O qcow2 myimg.raw myimg.qcow2 
$ rm myimg.raw 

オリジナルのイメージのパーミッションと合わせる:

$ chown --reference=myimg.qcow2.bak myimg.qcow2
$ chmod --reference=myimg.qcow2.bak myimg.qcow2

インストールメディアを準備する

ディスクイメージにオペレーティングシステムをインストールするには、オペレーティングシステムのインストールメディア (例: オプティカルディスク、USB ドライブ、ISO イメージ) が必要です。QEMU はメディアに直接アクセスできないのでインストールメディアをマウントしてはいけません。

ヒント: 光ディスクを使う場合、最初に中身をファイルに移動させると良いでしょう。パフォーマンスが発揮されるようになり、デバイスに直接アクセスする必要がなくなります (従って、メディアのデバイスファイルのアクセス権限を変えることなく QEMU を通常ユーザーで起動することが可能になります)。 例えば、 CD-ROM デバイスノードの名前が /dev/cdrom なら、次のコマンドでファイルに dump することが出来ます:
$ dd if=/dev/cdrom of=cd_image.iso bs=4k

オペレーティングシステムのインストール

ここで初めてエミュレータを起動することになります。ディスクイメージにオペレーティングをインストールするには、ディスクイメージとインストールメディアの両方を仮想マシンに結びつけて、インストールメディアから起動するようにする必要があります。

例えば i386 ゲストで、CD-ROM としてのブータブル ISO ファイルと raw ディスクイメージからインストールするには:

$ qemu-system-x86_64 -cdrom iso_image -boot order=d -drive file=disk_image,format=raw

他のメディアタイプ(フロッピー、ディスクイメージ、物理ドライブなど)の読み込みについては qemu(1) を、その他の便利なオプションについては #仮想化システムを実行する を見て下さい。

オペレーティングシステムのインストールが終了したら、直接 QEMU イメージを起動することができます( #仮想化システムを実行する を参照)。

{注意|デフォルトではマシンに割り当てられるメモリは 128MiB だけです。メモリの量は -m スイッチで調整できます。例えば -m 512M-m 2G 。}

ヒント:
  • 少なくとも設定中や実験中は、 -boot order=x を指定する代わりにブートメニュー: -boot menu=on を使う方が快適だと感じるユーザもいるかもしれません。
  • QEMUをヘッドレスモードで実行する場合、QEMU はデフォルトでポート5900でローカルVNCサーバを起動します。ゲストOSへの接続に TigerVNC を使用することができます: vncviewer :5900
  • インストールプロセスでフロッピーや CD を替える必要がある場合、QEMU マシンモニター (仮想マシンのウィンドウで Ctrl+Alt+2 を押す) を使って仮想マシンからストレージデバイスを取り外したりアタッチすることができます。ブロックデバイスを見るには info block を、デバイスをスワップアウトするには change コマンドを使って下さい。Ctrl+Alt+1 を押せば仮想マシンに戻ります。

仮想化システムを実行する

qemu-system-* バイナリ (例えば qemu-system-i386qemu-system-x86_64 など、エミュレートするアーキテクチャによって異なります) を使って仮想化システムを実行します。使用方法は:

$ qemu-system-x86_64 options disk_image

全ての qemu-system-* バイナリでオプションは共通です、全てのオプションのドキュメントは qemu(1) を見て下さい。

デフォルトで、QEMU は仮想マシンのビデオ出力をウィンドウに表示します。注意: QEMU ウィンドウの中をクリックすると、マウスポインタが取り込まれます。ポインタを戻すには、Ctrl+Alt+g を押して下さい。

警告: QEMU を root で実行しないでください。スクリプト内で root で実行する必要があるときは、-runas オプションを使って QEMU の root 特権を外して下さい。

KVM を有効にする

使用しているプロセッサとカーネルが KVM をサポートしている必要があります。また、必要なカーネルモジュールがロードされてなければなりません。詳しくは KVM を見て下さい。

QEMU を KVM モードで起動するには、起動オプションに -enable-kvm を追加してください。実行中の仮想マシンで KVM が有効になっているかどうか確認するには、Ctrl+Alt+Shift+2 を使って QEMU Monitor に入り、info kvm と入力してください。

ノート:
  • -machine オプションの引数 accel=kvm-enable-kvm または -accel kvm オプションと同等です。
  • CPU モデル host は KVM を必要とします。
  • GUI ツールを使って VM を起動した時にパフォーマンスが出ない場合、KVM サポートを確認してください。QEMU がソフトウェアエミュレーションにフォールバックしている可能性があります。
  • ブルースクリーンを出さずに Windows 7 や Windows 8 を正しく起動するには KVM を有効にする必要があります。

IOMMU (Intel VT-d/AMD-Vi) サポートを有効にする

IOMMU を使うことで PCI パススルーやメモリの保護などの機能が利用できます。Wikipedia:ja:IOMMU#利点Memory Management (computer programming): Could you explain IOMMU in plain English? を見てください。

IOMMU を有効化するには:

  1. CPU によって AMD-Vi/Intel VT-d がサポートされていること、BIOS の設定で有効になっていることを確認してください。
  2. Intel の CPU を使っている場合は intel_iommu=on、AMD の CPU を使っている場合は amd_iommu=onカーネルパラメータに追加してください。
  3. PCI パススルーのためだけに IOMMU が必要な場合、iommu=pt パラメータも追加してください。Linux がパススルーするデバイスの IOMMU だけを有効化できるようになり、システムの他のデバイスへのパフォーマンスの影響を避けられます。CPU メーカー別のパラメータ (上記) も on にする必要があります。
  4. 再起動して dmesgDMAR があることを確認して IOMMU が有効になっていることをチェックしてください: [0.000000] DMAR: IOMMU enabled
  5. -device intel-iommu を追加して IOMMU デバイスを作成してください:
$ qemu-system-x86_64 -enable-kvm -machine q35,accel=kvm -device intel-iommu -cpu host,hv_relaxed,hv_spinlocks=0x1fff,hv_vapic,hv_time ..
ノート: Intel の CPU が搭載されている場合、-device intel-iommu を使って QEMU ゲストに IOMMU デバイスを作成すると PCI パススルーが無効化されて以下のようなエラーが表示されることがあります:
Device at bus pcie.0 addr 09.0 requires iommu notifier which is currently not supported by intel-iommu emulation
(vfio-pci による PCI パススルーなど) IO をリマップするには intel_iommu=on カーネルパラメータの追加が必要ですが、PCI パススルーを使う場合は -device intel-iommu は設定してはいけません。

UEFIモードでの起動

QEMU が使用するデフォルトのファームウェアは SeaBIOS で、これはレガシー BIOS の実装です。QEMU はデフォルトの読み取り専用(ROM)イメージとして /usr/share/qemu/bios-256k.bin (seabios で提供される) を使用します。他のファームウェアファイルを選択するには -bios 引数を使用します。しかし、UEFI が正しく動作するためには書き込み可能なメモリが必要であるため、代わりに PC システムフラッシュ をエミュレートする必要があります。

OVMF は仮想マシンの UEFI サポートを有効にするための TianoCore プロジェクトです。 edk2-ovmf パッケージで インストール することができます。

OVMF をファームウェアとして使うには 2 つの方法があります。一つは /usr/share/edk2-ovmf/x64/OVMF.fd をコピーして書き込み可能にし、pflashドライブとして利用する方法です:

-drive if=pflash,format=raw,file=/copy/of/OVMF.fd.

UEFI 設定への全ての変更はこのファイルに直接保存されます。

もう一つのより好ましい方法は OVMF を二つのファイルに分割することです。最初のファイルは読み込み専用でファームウェアの実行ファイルを保存し、2番目のファイルは書き込み可能な変数ストアとして使われます。利点はファームウェアファイルをコピーせずに直接使うことができ、 pacman によって自動的にアップデートされることです。

/usr/share/edk2-ovmf/x64/OVMF_CODE.fd を最初のリードオンリーな pflash ドライブとして使用します。/usr/share/edk2-ovmf/x64/OVMF_VARS.fd をコピーして書き込み可能にし、2台目の書き込み可能な pflash ドライブとして使用します:

-drive if=pflash,format=raw,readonly=on,file=/usr/share/edk2-ovmf/x64/OVMF_CODE.fd \
-drive if=pflash,format=raw,file=/copy/of/OVMF_VARS.fd


Trusted Platform Module のエミュレーション

QEMUは、Windows 11などの一部のシステムで必要とされるTrusted Platform Module をエミュレートすることができます。

ソフトウェア TPM の実装を提供する swtpm パッケージをインストール します。 TPM のデータを格納するディレクトリを作成します(/path/to/mytpmを例として使用します)。以下のコマンドを実行し、エミュレータを起動します:

$ swtpm socket --tpm2 --tpmstate dir=/path/to/mytpm --ctrl type=unixio,path=/path/to/mytpm/swtpm-sock

/path/to/mytpm/swtpm-sockswtpm が作成します: これはQEMUが接続するUNIXソケットです。どのディレクトリに置いてもかまいません。

デフォルトでは、swtpm は TPM バージョン 1.2 エミュレータを起動します。 --tpm2 オプションを指定すると、TPM 2.0 のエミュレーションが有効になります。

最後に、QEMU に以下のオプションを追加します:

-chardev socket,id=chrtpm,path=/path/to/mytpm/swtpm-sock \
-tpmdev emulator,id=tpm0,chardev=chrtpm \
-device tpm-tis,tpmdev=tpm0

すると、VM 内で TPM が使用できるようになります。VM をシャットダウンすると、swtpmは自動的に終了します。

詳しくは the QEMU documentation を参照してください。

ホスト・ゲスト OS 間でデータを移動する

ネットワーク

ファイルを転送できるネットワークプロトコルであれば NFS, SMB, NBD, HTTP, FTP, SSH など何でも使ってホストとゲスト OS 間でデータを共有することができます、ただしネットワークを適切に設定して適切なサービスを有効にする必要があります。

デフォルトのユーザーモードネットワークは IP アドレス 10.0.2.2 でゲストがホスト OS にアクセスするのを許可します。ホスト OS で動作する全てのサーバー、SSH サーバーや SMB サーバーなどは、この IP アドレスでアクセスすることが可能になります。そしてゲストでは、SMBNFS でホストのディレクトリをマウントしたり、ホストの HTTP サーバーなどにアクセスすることが可能です。 ゲスト OS で動作しているサーバーにホスト OS がアクセスすることはできませんが、他のネットワーク設定を使えば不可能ではありません (#QEMU の Tap ネットワーク を参照)。

QEMUのポートフォワーディング

QEMUのポートフォワーディングはIPv4のみです。

ノート: QEMUのポートフォワーディングは IPv4 のみです。IPv6 ポート転送は実装されておらず、最後のパッチは 2018 年に提案されました [1]

QEMUはホストからゲストへポートを転送し、例えばホストからゲスト上で動作しているSSHサーバーへの接続を可能にします。

例えば、ホストのポート 60022 とゲストのポート 22(SSH) をバインドするには、次のようなコマンドでQEMUを起動します:

$ qemu-system-x86_64 disk_image -nic user,hostfwd=tcp::60022-:22

ゲストで sshd が動いていることを確認し、接続します:

$ ssh guest-user@127.0.0.1 -p 60022

SSHFS を使って共有読み込みと書き込みのためにゲストのファイルシステムをホストにマウントできます。

複数のポートを転送するには、hostfwd-nic 引数で繰り返すだけです、例えば VNC のポートは次のようになります:

$ qemu-system-x86_64 disk_image -nic user,hostfwd=tcp::60022-:22,hostfwd=tcp::5900-:5900

QEMUの内蔵SMBサーバ

QEMUのドキュメントには "内蔵の" SMBサーバーがあると書かれていますが、実際は tmp/qemu-smb.ランダムな文字列 にある自動生成の smb= で共有設定できるのは1つのディレクトリだけですが、QEMUがシンボリックリンクに従うようにSMBを設定すれば、(仮想マシン実行中でも)共有ディレクトリにシンボリックリンクを作成するだけで簡単に他のディレクトリを追加できます。このようなことをすることはありませんが、実行中のSMBサーバーの設定を後述のように変更することができます。

ホスト上にSambaがインストールされている必要があります。この機能を有効にするには、次のようなコマンドでQEMUを起動します。

$ qemu-system-x86_64 -nic user,id=nic0,smb=shared_dir_path disk_image

shared_dir_path はゲストとホストで共有したいディレクトリです。

これで、ゲストから、ホスト 10.0.2.4 上の共有ディレクトリに 共有名 "qemu" でアクセスできるようになります。例えば、Windowsエクスプローラで \\10.0.2.4\qemu に移動します。

ノート:
  • -net user,smb=shared_dir_path1 -net user,smb=shared_dir_path2-net user,smb=shared_dir_path1,smb=shared_dir_path2 のように共有オプションを複数回使用した場合、最後に定義したものだけが共有されます。
  • ゲストシステムがWindowsで共有フォルダにアクセスできない場合、NetBIOSプロトコルが有効になっているかどうか とNetBIOSプロトコルが使用する ポート がファイアウォールでブロックされていないか確認してください。
  • 共有フォルダーにアクセスできず、ゲストシステムがWindows 10 Enterprise または Education、Windows Server 2016 の場合、ゲストアクセスを有効にします
  • #Tap networking with QEMU を使用する場合、 SMB を取得するには -device virtio-net,netdev=vmnic -netdev user,id=vmnic,smb=shared_dir_path を使います。

複数のディレクトリを共有し、仮想マシンの実行中にディレクトリの追加や削除を行う方法として、空のディレクトリを共有し、共有ディレクトリ内のディレクトリへのシンボリックリンクを作成/削除する方法があります。これを機能させるには、実行中のSMBサーバーの設定を以下のスクリプトで変更します。これは、ホスト側で実行可能に設定されていないファイルのゲスト側での実行も許可します。

#!/bin/sh
eval $(ps h -C smbd -o pid,args | grep /tmp/qemu-smb | gawk '{print "pid="$1";conf="$6}')
echo "[global]
allow insecure wide links = yes
[qemu]
follow symlinks = yes
wide links = yes
acl allow execute always = yes" >> "$conf"
# in case the change is not detected automatically:
smbcontrol --configfile="$conf" "$pid" reload-config

これはゲストが初めてネットワークドライブに接続した後にのみ、qemuによって起動された実行中のサーバーに適用することができます。この代わりに、次のように設定ファイルに追加の共有を追加する方法があります:

echo "[myshare]
path=another_path
read only=no
guest ok=yes
force user=username" >> $conf

この共有はゲスト上で \\10.0.2.4\myshare として利用可能になります。

ファイルシステムパススルーと VirtFS を使う

https://wiki.qemu.org/Documentation/9psetup QEMU ドキュメント] を参照してください。

virtiofsd によるホストファイル共有

virtiofsd は QEMU パッケージに同梱されています。 virtiofsd は QEMU パッケージと一緒に出荷されます。 ドキュメントは オンライン または /usr/share/doc/qemu/tools/virtiofsd.html が QEMU がインストールされたローカルファイルシステムで入手できます。

virtiofsd ソケットにアクセスする必要があるため、qemu を実行するユーザを 'kvm' グループに追加します。変更を反映するにはログアウトする必要があるかもしれません。

virtiofsd を root で起動します:

# /usr/lib/qemu/virtiofsd --socket-path=/var/run/qemu-vm-001.sock -o source=/tmp/vm-001 -o cache=always

ここで

  • /var/run/qemu-vm-001.sock はソケットファイルです。
  • /tmp/vm-001 はホストとゲスト vm の共有ディレクトリです。

作成されたソケットファイルは root のみアクセス権を持っています。以下のようにグループ kvm にアクセス権を与えます:

# chgrp kvm qemu-vm-001.sock; chmod g+rxw qemu-vm-001.sock

VM起動時に以下の設定オプションを追加します:

-object memory-backend-memfd,id=mem,size=4G,share=on \
-numa node,memdev=mem \
-chardev socket,id=char0,path=/var/run/qemu-vm-001.sock \
-device vhost-user-fs-pci,chardev=char0,tag=myfs

ここで

  • size=4G-m 4G オプションで指定したサイズと一致する必要があります。
  • /var/run/qemu-vm-001.sock は先に起動されたソケットファイルを指します。

ゲストでは共有が有効となるように設定されている必要があることに注意してください。 Windows の場合、手順書 があります。一度設定すると、Windows の Z: ドライブに共有ディレクトリの内容が自動的にマップされます。

以下のものがあれば、Windows 10 ゲストシステムは適切に設定されています。

  • VirtioFSSService windows サービス
  • WinFsp.Launcher windows サービス
  • Windows の"デバイスマネージャー"の"システムデバイス"の下の VirtIO FS Device driver

上記がインストールされていても Z: ドライブが表示されない場合は、Windowsのプログラムの追加と削除から"Virtio-win-guest-tools"を修復してみてください。

ゲストのパーティションをホストにマウントする

ホストシステムの下にドライブイメージをマウントすると、ゲストへのファイルの出し入れに便利な場合があります。これは仮想マシンが動作していないときに行う必要があります。

ホストにドライブをマウントする手順は、qemu イメージの rawqcow2 といった種類によって異なります。この2つの形式のドライブをマウントする手順については、#rawイメージからのパーティションのマウント#qcow2イメージからのパーティションのマウント で詳しく説明します。完全なドキュメントは Wikibooks:QEMU/Images#Mounting an image on the host を参照してください。

警告: 仮想マシンを再実行する前に、パーティションをアンマウントする必要があります。さもないと、データの破損が発生する可能性が非常に高くなります。

raw イメージからパーティションをマウントする

ループバックデバイスとして設定することで、 raw ディスクイメージファイル内のパーティションをマウントできます。

手動でバイトオフセットを指定する

ディスクイメージのパーティションをマウントする一つの方法として、次のようなコマンドを使って特定のオフセットでディスクイメージをマウントする方法があります:

# mount -o loop,offset=32256 disk_image mountpoint

offset=32256 オプションは、実際には losetup プログラムに渡され、ファイルのバイトオフセット 32256 から始まり最後まで続くループバックデバイスをセットアップします。そしてこのループバックデバイスがマウントされます。パーティションの正確なサイズを指定するために sizelimit オプションを使うこともできますが、これは通常は不要です。

ディスクイメージによっては、必要なパーティションがオフセット32256で始まらないかもしれません。fdisk は開始と終了のオフセットを 512 バイトのセクタで示しますので、512 倍して mount に渡すべき正しいオフセットを求めてください。 ディスクイメージによって、必要なパーティションがオフセット 32256 から始まってない可能性があります。 fdisk -l disk_image を実行してイメージ内のパーティションを見て下さい。fdisk は512バイトセクタ単位で起点と終点を表示するので、512 を掛けて適当なオフセットを mount で指定してください。

loop モジュールでパーティションを自動検出する

Linuxの loop ドライバは、実際にはループバックデバイスのパーティションをサポートしていますが、デフォルトでは無効になっています。有効にするには、以下のようにしてください:

  • ループバックデバイスを全て取り除いてください (マウントされているイメージをすべてアンマウントするなど)。
  • loop カーネルモジュールを アンロード し、 max_part=15 パラメータを設定してロードしてください。また、loop デバイスの最大数は max_loop パラメータで制御できます。
ヒント: 毎回 max_part=15 で loop モジュールをロードするには、カーネルに loop.ko モジュールが組み込まれているかどうかにあわせて、 /etc/modprobe.d にエントリを記述するか、カーネルコマンドラインに loop.max_part=15 と記述します。

イメージをループバックデバイスとして設定:

# losetup -f -P disk_image

これで、作成されたデバイスが /dev/loop0 の場合、追加のデバイス /dev/loop0pX が自動的に作成されます。X はパーティションの番号です。これらのパーティションのループバックデバイスは直接マウントすることができます。例えば:

# mount /dev/loop0p1 mountpoint

udisksctl でディスクイメージをマウントする方法は Udisks#ループデバイスのマウント を参照してください。

kpartxを使う

multipath-tools パッケージの kpartx はデバイス上のパーティションテーブルを読み込んでパーティションごとに新しいデバイスを作成することができます。例えば:

# kpartx -a disk_image

これでループバックデバイスがセットアップされ、/dev/mapper/ に必要なパーティションデバイスが作成されます。

qcow2 イメージからパーティションをマウントする

NBD (network block device) プロトコルを使ってディスクイメージを共有することができる qemu-nbd を使用してみます。

まず、nbdモジュールをロードする必要があります:

# modprobe nbd max_part=16

次に、ディスクを共有してデバイスエントリを作成します:

# qemu-nbd -c /dev/nbd0 /path/to/image.qcow2

パーティションを検出します:

# partprobe /dev/nbd0

fdisk を使用して nbd0 内のさまざまなパーティションに関する情報を取得できます:

# fdisk -l /dev/nbd0
Disk /dev/nbd0: 25.2 GiB, 27074281472 bytes, 52879456 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xa6a4d542

Device      Boot   Start      End  Sectors  Size Id Type
/dev/nbd0p1 *       2048  1026047  1024000  500M  7 HPFS/NTFS/exFAT
/dev/nbd0p2      1026048 52877311 51851264 24.7G  7 HPFS/NTFS/exFAT

次に、ドライブイメージの任意のパーティション、例えばパーティション2をマウントします:

# mount /dev/nbd0p2 'mountpoint

使用後は、イメージをアンマウントし、前の手順を逆にすることが重要です。つまり、パーティションをアンマウントし nbd デバイスを切断します:

# umount mountpoint
# qemu-nbd -d /dev/nbd0

qcow2 イメージの中にパーティションをマウントする

qcow2 イメージの中のパーティションは qemu-nbd を使ってマウントできます。Wikibooks を見て下さい。

実際のパーティションをハードディスクイメージのシングルプライマリパーティションとして使う

場合によって、QEMU の中からシステムパーティションのどれかを使いたくなることもあるでしょう。仮想マシンでの raw パーティションの使用は、読み書きの操作が物理ホストのファイルシステムレイヤーを通過しないため、パフォーマンスが高くなります。そのようなパーティションをホストとゲストでのデータの共有手段として使うこともできます。

Arch Linux では、raw パーティションのデバイスファイルは、デフォルトで、rootdisk グループが所有者です。root 以外のユーザーで raw パーティションに読み書きできるようにしたい場合は、パーティションのデバイスファイルの所有者をそのユーザーに変えるか、そのユーザーをdiskグループに追加するか、ACL を使用してより詳細なアクセス制御を行う必要があります。

警告:
  • 仮想マシンにホストシステムのクリティカルなデータ (root パーティションなど) を変更する許可を与えるのは可能ではありますが、推奨はされません。
  • ホストとゲストの両方で同時にパーティションのファイルシステムを読み書き可能でマウントしてはいけません。そうすると、データが破壊される可能性があります。

その後、パーティションを QEMU の仮想マシンに仮想ディスクとしてアタッチできます。

ただし、仮想マシン全体をパーティションに収めたいときは、事態は多少複雑になります。そのような場合、実際に仮想マシンを起動するディスクイメージファイルがないために、MBR でパーティション分けされたデバイスではなくファイルシステムとしてフォーマットされたパーティションにブートローダーをインストールすることができません。このような仮想マシンは次のいずれかの方法でブートできます: #カーネルと initrd を手動で指定する#MBR で仮想ディスクをシミュレートする#device-mapper を使う#リニア RAID を使う、または#ネットワークブロックデバイスを使う

カーネルと initrd を手動で指定する

QEMU は GRUB などのブートローダーを迂回して、Linux カーネルinit ramdisk を直接ロードすることをサポートしています。それから root ファイルシステムを含んでいる物理パーティションで、パーティションされていない仮想ディスクとして起動することができます。以下のようなコマンドを実行することで行います:

ノート: この例で使用するのはゲストのイメージではなく、ホストのイメージです。ゲストのイメージを使いたい場合は、(ホストからファイルシステムを保護するために) /dev/sda3 を読み取り専用でマウントして /full/path/to/images と指定するか、ゲストで kexec を使ってゲストのカーネルをリロードしてください (起動時間を拡張します)。
$ qemu-system-x86_64 -kernel /boot/vmlinuz-linux -initrd /boot/initramfs-linux.img -append root=/dev/sda /dev/sda3

上の例では、ゲストの root ファイルシステムに使われている物理パーティションはホストの /dev/sda3 で、ゲストでは /dev/sda として表示されます。

もちろん、Arch Linux で使われているものとは違うカーネルや initrd を自由に指定することができます。

複数のカーネルパラメータ-append オプションで指定するときは、クォートを使って囲む必要があります。例:

... -append 'root=/dev/sda1 console=ttyS0'

MBR で仮想ディスクをシミュレートする

ファイルシステムでフォーマットされたパーティションを維持しながらゲストのパーティションをまるでディスクであるかのようなパーティションにしないで、仮想マシンで物理パーティションを使用するもっと複雑な方法として、MBR をシミュレートして GRUB などのブートローダーを使って起動できるようにする方法があります。

次の例では、マウントされていないプレーンな テンプレート:Ic/dev/hda''N' パーティションがあり、その中に QEMU ディスクイメージの一部にしたいファイルシステムがあるとします。秘訣は、 QEMU rawディスクイメージに組み込みたい実パーティションに、動的にマスターブートレコード (MBR) を付加することです。より一般的には、このパーティションは、より大きなシミュレートされたディスクの任意の部分、特に元の物理ディスクをシミュレートしますが テンプレート:Ic/dev/hda''N' だけを仮想マシンに公開するブロックデバイスにすることができます。

このタイプの仮想ディスクは、MBRとパーティションへの参照(コピー)を含む VMDK ファイルで表すことができますが、 QEMU はこの VMDK フォーマットをサポートしていません。たとえば、 以下のように作成された 仮想ディスクは

$ VBoxManage internalcommands createrawvmdk -filename /path/to/file.vmdk -rawdisk /dev/hda

以下のエラーメッセージとともに QEMU によって拒否されます

Unsupported image type 'partitionedDevice'

VBoxManagefile.vmdkfile-pt.vmdk の2つのファイルを作成します。後者は MBR のコピーであり、テキスト・ファイル file.vmdk が参照します。ターゲットパーティションまたは MBR の外側への読取り操作にはゼロが返され、書き込まれたデータは破棄されます。

device-mapper を使う

VMDK ディスクリプタ・ファイルを利用するのと同様の方法で、 device-mapper を利用して、 MBR ファイルに付属するループ・デバイスを対象パーティションにプリペンドする方法があります。仮想ディスクのサイズがオリジナルと同じである必要がない場合、まずMBRを保持するためのファイルを作成します。

$ dd if=/dev/zero of=/path/to/mbr count=2048

これで、最新のディスクパーティションツールが使用するパーティションアライメントポリシーに従った 1 MiB (2048*512バイト) のファイルが作成されます。古いパーティショニングソフトウェアとの互換性のために、2048セクタではなく63セクタが必要になる場合があります。MBR に必要なブロックは 512 バイトのみです。追加の空き領域は BIOS ブートパーティションや、ハイブリッドパーティショニングスキームの場合は GUID パーティションテーブルに使用できます。次に、ループデバイスを MBR ファイルにアタッチします:

# losetup --show -f /path/to/mbr
/dev/loop0

この例では、結果のデバイスは /dev/loop0 です。device mapper を使って MBR とパーティションを結合します:

# echo "0 2048 linear /dev/loop0 0
2048 `blockdev --getsz /dev/hdaN` linear /dev/hdaN 0" | dmsetup create qemu

生成された /dev/mapper/qemu は、 QEMU の raw ディスクイメージとして使用します。仮想ディスク上にパーティションテーブル(例としてリニア RAID の使用について説明したセクションを参照)とブートローダーコード(/path/to/mbr に保存されます)を作成するには、追加の手順が必要です。

次の設定例では、仮想ディスク上の /dev/hdaN' の位置を物理ディスク上と同じにし、コピーとして提供されるMBRを除き、ディスクの残りの部分を非表示にしています。

# dd if=/dev/hda count=1 of=/path/to/mbr
# loop=`losetup --show -f /path/to/mbr`
# start=`blockdev --report /dev/hdaN | tail -1 | awk '{print $5}'`
# size=`blockdev --getsz /dev/hdaN`
# disksize=`blockdev --getsz /dev/hda`
# echo "0 1 linear $loop 0
1 $((start-1)) zero
$start $size linear /dev/hdaN 0
$((start+size)) $((disksize-start-size)) zero" | dmsetup create qemu

dmsetup への標準入力として提供されるテーブルは、 VBoxManage によって作成された VDMK 記述子ファイル内のテーブルと同様のフォーマットを持ち、代わりに dmsetup create qemu--tabletable_file でファイルからロードできます。仮想マシンには /dev/hdaN だけがアクセス可能で、ハードディスクの残りはゼロとして読み取られ、書き込まれたデータは最初のセクタを除いて破棄されます。 dmsetup table qemu/dev/mapper/qemu のテーブルを表示できます (udevadm info -rq name /sys/dev/block/major:minormajor:minor/dev/blockdevice 名に変換してください) 。作成されたデバイスを削除するには dmsetup remove qemulosetup -d $loop を使います。

この例が役に立つ状況は、マルチブート構成の既存の Windows XP インストールと、おそらくハイブリッドパーティションスキーム(物理ハードウェアでは、Windows XP が MBR パーティションテーブルを使用する唯一のオペレーティングシステムであり、同じコンピュータにインストールされた最新のオペレーティングシステムは GUID パーティションテーブルを使用できます)の場合です。Windows XP はハードウェアプロファイルをサポートしているため、同じインストールを異なるハードウェア構成で交互に使用できます(この場合はベアメタルと仮想)。Windows は新しく検出されたハードウェアのドライバをプロファイルごとに1回だけインストールする必要があります。この例ではコピーされた MBR のブートローダコードを更新して、元のシステムに存在するマルチブート対応のブートローダ(GRUB など)を起動するのではなく、 /dev/hdaN から直接 Windows XP をロードする必要があることに注意してください。または、ブートローダインストールを含むブートパーティションのコピーを MBR と同じ方法で仮想ディスクに含めることもできます。

リニア RAID を使う

リニアモードのソフトウェア RAID (linear.ko カーネルドライバが必要です)とループバックデバイスを使うこともできます:

最初に、MBRを保持する小さなファイルを作成します:

$ dd if=/dev/zero of=/path/to/mbr count=32

これで 16 KB (32 * 512 バイト) のファイルが作成されます。(MBR は512バイトのブロックしか必要としませんが) あまり小さくしすぎないことが重要です。なぜならファイルを小さくすればするほど、ソフトウェア RAID デバイスのチャンクサイズも小さくしなくてはならなくなり、パフォーマンスに影響を与えるからです。次に、MBR ファイルのループバックデバイスを設定します:

# losetup -f /path/to/mbr

他にループバックを使っていないために、作成されるデバイスは /dev/loop0 になるとします。次のステップはソフトウェア RAID を使って "merged" MBR + /dev/hdaN ディスクイメージを作成することです:

# modprobe linear
# mdadm --build --verbose /dev/md0 --chunk=16 --level=linear --raid-devices=2 /dev/loop0 /dev/hdaN

作成した /dev/md0 は QEMU の raw ディスクイメージとして使用します (エミュレータがアクセスできるようにパーミッションを設定するのを忘れないでください)。最後にプライマリパーティションの開始位置が /dev/md0/dev/hdaN に一致するようにディスクの設定 (ディスクのジオメトリとパーティションテーブルの設定) を行います (上の例では 16 * 512 = 16384 バイトのオフセットです)。ホストマシンで fdisk を使って行ってください。エミュレータの中で行ってはいけません: QEMU のデフォルトのディスク認識ルーチンによってキロバイトで割り切れないオフセットが生まれるとソフトウェア RAID コードで管理できなくなります。ホストから以下を実行してください:

# fdisk /dev/md0

X を押してエキスパートメニューを開きます。トラック毎のセクタ数を設定してシリンダーの容量が MBR ファイルの容量に一致するようにしてください。ヘッダが2つでセクタサイズが512の場合、1トラックあたりのセクタ数は16となり、シリンダのサイズは 2x16x512=16k になります。

R を押してメインメニューに戻って下さい。

P を押してシリンダーのサイズが 16k になってることを確認します。

/dev/hdaN にあわせてシングルプライマリパーティションを作成してください。パーティションの開始位置はシリンダー2で終了位置はディスクの末尾になります (シリンダーの数は fdisk に入力したときの値で変わります)。

最後に、結果をファイルに書き出してください ('w')。これでホストから直接パーティションをディスクイメージとしてマウントすることができます:

$ qemu-system-x86_64 -hdc /dev/md0 [...]

もちろん、元のパーティション /dev/hdaN に必要ツールが含まれていれば、QEMU を使ってディスクイメージにブートローダーを設定できます。

ネットワークブロックデバイスを使う

Network Block Device によって、Linux はリモートサーバをブロックデバイスの1つとして使うことができます。 nbd-server (nbd パッケージ)を使って、QEMU 用の MBR ラッパーを作成することができます。

上記のように MBR ラッパーファイルを設定したら、wrapper.img.0 に名前を変更してください。そして同じディレクトリに wrapper.img.1 という名前のシンボリックリンクを作成して、パーティションにリンクするようにしてください。また、同じディレクトリに以下のスクリプトを作成します:

#!/bin/sh
dir="$(realpath "$(dirname "$0")")"
cat >wrapper.conf <<EOF
[generic]
allowlist = true
listenaddr = 127.713705
port = 10809

[wrap]
exportname = $dir/wrapper.img
multifile = true
EOF

nbd-server \
    -C wrapper.conf \
    -p wrapper.pid \
    "$@"

.0.1 という拡張子が重要です。他は変えてもかまいません。上記のスクリプトを実行後 (nbd-server がパーティションにアクセスできるように root で実行してください)、以下のコマンドで QEMU を起動できます:

qemu-system-x86_64 -drive file=nbd:127.713705:10809:exportname=wrap [...]

ネットワーク

仮想ネットワークのパフォーマンスはユーザーモードネットワークまたは vde によるよりも tap デバイスやブリッジを用いる方が良いでしょう。tap デバイスやブリッジはカーネル内で実装されているからです。

加えて、デフォルトの e1000 NIC のエミュレーションではなく virtio ネットワークデバイスを仮想マシンに指定することでネットワークのパフォーマンスを向上させることができます。詳しくは #virtio ドライバーのインストール を参照。

リンク層アドレス

QEMU に -net nic 引数を与えると、デフォルトで、仮想マシンにリンク層アドレス 52:54:00:12:34:56 のネットワークインターフェイスが割り当てられます。しかしながら、ブリッジネットワークで複数の仮想マシンを使用する場合、個別の仮想マシンにはタップデバイスの仮想マシン側からそれぞれ固有のリンク層 (MAC) アドレスを設定しなくてはなりません。設定を行わないと、ブリッジが上手く動きません。同一のリンク層アドレスを持つ複数のソースからパケットを受け取ることになるからです。たとえタップデバイス自体に固有のリンク層アドレスを設定していたとしても、ソースのリンク層アドレスはタップデバイスを通過するときに書き換えられないため、問題が発生します。

個々の仮想マシンに固有のリンク層アドレスを設定、それも、どのアドレスも 52:54: で始まるように設定してください。以下のオプションを使って下さい (X は任意の16進数の数字に置き換えてください):

$ qemu-system-x86_64 -net nic,macaddr=52:54:XX:XX:XX:XX -net vde disk_image

固有のリンク層アドレスの生成は複数の方法で行うことができます:

1. NIC ごとに固有のリンク層アドレスを手動で指定する。仮想マシンを起動するたびに同じ IP アドレスが DHCP サーバーによって割り当てられるという利点がありますが、仮想マシンが大量にある場合は現実的ではありません。

2. 仮想マシンを起動するたびにランダムなリンク層アドレスを生成する。衝突する可能性はほとんどゼロですが、DHCP サーバーによって割り当てられる IP アドレスが毎回異なるのが欠点です。以下のコマンドをスクリプトで使うことで macaddr 変数にランダムなリンク層アドレスを生成できます:

printf -v macaddr "52:54:%02x:%02x:%02x:%02x" $(( $RANDOM & 0xff)) $(( $RANDOM & 0xff )) $(( $RANDOM & 0xff)) $(( $RANDOM & 0xff ))
qemu-system-x86_64 -net nic,macaddr="$macaddr" -net vde disk_image

3. 以下のスクリプト qemu-mac-hasher.py を使ってハッシュ関数を利用し仮想マシンの名前からリンク層アドレスを生成する。仮想マシンの名前を一意なものとして、上記の方法の良いところを組み合わせています。スクリプトが実行されるたびに同一のリンク層アドレスが生成される上、衝突する可能性はほとんどありません。

qemu-mac-hasher.py
#!/usr/bin/env python

import sys
import zlib

if len(sys.argv) != 2:
    print("usage: %s <VM Name>" % sys.argv[0])
    sys.exit(1)

crc = zlib.crc32(sys.argv[1].encode("utf-8")) & 0xffffffff
crc = str(hex(crc))[2:]
print("52:54:%s%s:%s%s:%s%s:%s%s" % tuple(crc))

以下のように使うことができます:

vm_name="VM Name"
qemu-system-x86_64 -name "$vm_name" -net nic,macaddr=$(qemu-mac-hasher.py "$vm_name") -net vde disk_image

ユーザーモードネットワーク

デフォルトで、-netdev 引数をつけていないと、QEMU は DHCP サーバーが内蔵されたユーザーモードネットワークを使用します。DHCP クライアントを実行したときに仮想マシンには IP アドレスが与えられ、QEMU による IP マスカレードを通して物理ホストのネットワークにアクセスできるようになります。

ノート: ICMPv6 のサポートは実装されていないため、動作しません: Slirp: 外部 icmpv6 はまだサポートされていません。IPv6 アドレスへの Ping は動作しません。

ホストがインターネットに接続されていれば、このデフォルトの設定で簡単に仮想マシンをインターネットにアクセスさせることができますが、外部ネットワークからは仮想マシンは直接は見えず、また、複数の仮想マシンを同時に起動していても仮想マシン同士が通信することはできません。

QEMU のユーザーモードネットワークには内蔵の TFTP や SMB サーバー、ゲストを VLAN に追加してゲストの通信を可能にするなどの機能があります。詳しくは -net user フラグの QEMU ドキュメントを参照してください。

ただし、ユーザーモードネットワークには有用性とパフォーマンスの両方で制約があります。より高度なネットワーク設定をするには tap デバイスや他の方法を使って下さい。

ノート: ホスト環境が systemd-networkd を使用している場合、systemd-networkd#必要なサービスと設定に書かれているように /etc/resolv.conf ファイルのシンボリックリンクを作成してください。作成しないとゲスト環境で DNS ルックアップができなくなります。
ヒント: ユーザーモードネットワークで virtio ドライバーを使用するためのオプションは次の通りです: -nic user,model=virtio-net-pci

QEMU の Tap ネットワーク

Tap デバイスは Linux カーネルの機能で、本当のネットワークインターフェイスのように見える仮想ネットワークインターフェイスを作成することができます。tap インターフェイスに送られたパケットは、そのインターフェイスに bind された、QEMU などのユーザースペースプログラムに送信されます。

QEMU は仮想マシンで tap ネットワークを利用して、tap インターフェイスに送られたパケットを仮想マシンに送信することで仮想マシンのネットワークインターフェイス (通常は Ethernet インターフェイス) から受け取ったように見せることが可能です。逆に、仮想マシンがネットワークインターフェイスを通して送信したものは全て tap インターフェイスが受け取ります。

Tap デバイスは Linux の bridge ドライバーによってサポートされているため、tap デバイスを互いに、または eth0 といったホストのインターフェイスとブリッジすることができます。これは、仮想マシンを互いに通信できるようにしたい場合や、LAN 上の他のマシンが仮想マシンに通信できるようにしたい場合に価値があります。

警告: tap デバイスとホストのインターフェイス (eth0 など) をブリッジすると、仮想マシンは外部ネットワークから直接認識されるようになり、攻撃を受ける可能性が出てきます。仮想マシンからアクセスできるリソースに応じて、通常のコンピュータと同じような対策を施して仮想マシンを防護するようにしてください。仮想マシンのリソースがほとんどなかったり複数の仮想マシンを立ち上げるなど危険性が高すぎる場合、ホストオンリーネットワークを使って NAT を設定するほうが良いでしょう。その場合、ゲストごとにファイアウォールを設定する必要はなく、ホストだけにファイアウォールを設定すれば十分です。

ホストオンリーネットワーク

ブリッジに IP アドレスが与えられていてそこへのトラフィックが許可されていながら、本当のインターフェイス (例: eth0) がブリッジに接続されていない場合、仮想マシンは互いに通信したりホストシステムと通信することができるようになります。しかしながら、物理ホストで IP マスカレードを設定しないかぎり外部ネットワークとは一切通信することができません。この設定は VirtualBox などの他の仮想化ソフトウェアではホストオンリーネットワークと呼ばれています。

ヒント:
  • IP マスカレードを設定したい場合、インターネット共有#NAT の有効化ページを見てください。
  • ブリッジインターフェイスで DHCP サーバーを実行して仮想ネットワークを構築することもできます。例えば 172.20.0.1/16 サブネットで DHCP サーバーとして dnsmasq を使うには:
# ip addr add 172.20.0.1/16 dev br0
# ip link set br0 up
# dnsmasq --interface=br0 --bind-interfaces --dhcp-range=172.20.0.2,172.20.255.254

内部ネットワーク

ブリッジに IP アドレスを与えずにブリッジへの全てのトラフィックを INPUT チェインで drop する iptables ルールを追加した場合、仮想マシンは互いに通信することはできても、物理ホストや外側のネットワークに接続できなくなります。この設定は VirtualBox などの他の仮想化ソフトウェアでは内部ネットワークと呼ばれています。仮想マシンに固定 IP アドレスを割り当てるかマシンのどれか一つで DHCP サーバーを実行する必要があります。

デフォルトで iptables はブリッジネットワークのパケットを拒否します。ブリッジネットワークのパケットを許可する iptables のツールを使用する必要があります:

# iptables -I FORWARD -m physdev --physdev-is-bridged -j ACCEPT

qemu-bridge-helper を使用するブリッジネットワーク

この方法にはスタートアップスクリプトが必要なく、すぐに複数の tap やブリッジに対応することができます。 /usr/lib/qemu/qemu-bridge-helper バイナリを使用して、既存のブリッジに tap デバイスを作成できます。

ヒント:

まず、QEMU が使用するすべてのブリッジの名前を含む設定ファイルを作成します。

/etc/qemu/bridge.conf
allow br0
allow br1
...

/etc/qemu/パーミッション755 であることを確認してください。そうでない場合、 QEMU の問題GNS3 の問題 が発生する可能性があります。

次に VM を起動します; デフォルトのネットワークヘルパーとデフォルトのブリッジ br0 で QEMU を実行する最も基本的な使い方は:

$ qemu-system-x86_64 -nic bridge [...]

ブリッジ br1 と virtio ドライバを使用するには:

$ qemu-system-x86_64 -nic bridge,br=br1,model=virtio-net-pci [...]'...

ブリッジを手動で作成する

ヒント: QEMU 1.1 から、スクリプトを追加することなく network bridge helper で tun/tap を設定することができます。#qemu-bridge-helper を使用するブリッジネットワーク を参照。

以下では仮想マシンを eth0 などのホストインターフェイスにブリッジする方法を説明しています。おそらく一番よく使われている設定です。この設定では、物理的なホストマシンと同一の Ethernet セグメントに、直接外部ネットワークに仮想マシンが位置するようになります。

通常の Ethernet アダプタをブリッジアダプタで置き換えて、通常の Ethernet アダプタをブリッジアダプタに bind することにします。

  • ブリッジを制御するための brctl が入っている bridge-utils をインストール。
  • IPv4 フォワーディングを有効にする:
# sysctl -w net.ipv4.ip_forward=1

変更を永続的にするために、/etc/sysctl.d/99-sysctl.confnet.ipv4.ip_forward = 0net.ipv4.ip_forward = 1 に変えます。

  • tun モジュールをロードして起動時にロードするように設定してください。詳しくはカーネルモジュールを参照。
  • オプションでブリッジを作成します。詳細は netctl でブリッジ接続 を参照してください。ブリッジに br0 という名前を付けるか、以下のスクリプトをブリッジの名前に変更してください。以下の run-qemu スクリプトでは、リストにない場合は br0 が設定されます。これは、デフォルトではホストがブリッジを介してネットワークにアクセスしていないと想定されているからです。
/etc/qemu-ifup
#!/bin/sh

echo "Executing /etc/qemu-ifup"
echo "Bringing up $1 for bridged mode..."
sudo /usr/bin/ip link set $1 up promisc on
echo "Adding $1 to br0..."
sudo /usr/bin/brctl addif br0 $1
sleep 2
  • QEMU 用に root:kvm 750 パーミッションで /etc/qemu-ifdown の tap アダプタを落とすスクリプトを作成:
/etc/qemu-ifdown
#!/bin/sh

echo "Executing /etc/qemu-ifdown"
sudo /usr/bin/ip link set $1 down
sudo /usr/bin/brctl delif br0 $1
sudo /usr/bin/ip link delete dev $1
  • visudo を使って sudoers ファイルに以下を追加します:
Cmnd_Alias      QEMU=/usr/bin/ip,/usr/bin/modprobe,/usr/bin/brctl
%kvm     ALL=NOPASSWD: QEMU
  • 以下の run-qemu スクリプトを使って QEMU を起動します:
run-qemu
#!/bin/bash
: '
e.g. with img created via:
qemu-img create -f qcow2 example.img 90G
run-qemu -cdrom archlinux-x86_64.iso -boot order=d -drive file=example.img,format=qcow2 -m 4G -enable-kvm -cpu host -smp 4
run-qemu -drive file=example.img,format=qcow2 -m 4G -enable-kvm -cpu host -smp 4
'

nicbr0() {
    sudo ip link set dev $1 promisc on up &> /dev/null
    sudo ip addr flush dev $1 scope host &>/dev/null
    sudo ip addr flush dev $1 scope site &>/dev/null
    sudo ip addr flush dev $1 scope global &>/dev/null
    sudo ip link set dev $1 master br0 &> /dev/null
}
_nicbr0() {
    sudo ip link set $1 promisc off down &> /dev/null
    sudo ip link set dev $1 nomaster &> /dev/null
}

HASBR0="$( ip link show | grep br0 )"
if [ -z $HASBR0 ] ; then
    ROUTER="192.168.1.1"
    SUBNET="192.168.1."
    NIC=$(ip link show | grep enp | grep 'state UP' | head -n 1 | cut -d":" -f 2 | xargs)
    IPADDR=$(ip addr show | grep -o "inet $SUBNET\([0-9]*\)" | cut -d ' ' -f2)
    sudo ip link add name br0 type bridge &> /dev/null
    sudo ip link set dev br0 up
    sudo ip addr add $IPADDR/24 brd + dev br0
    sudo ip route del default &> /dev/null
    sudo ip route add default via $ROUTER dev br0 onlink
    nicbr0 $NIC
    sudo iptables -I FORWARD -m physdev --physdev-is-bridged -j ACCEPT
fi

USERID=$(whoami)
precreationg=$(ip tuntap list | cut -d: -f1 | sort)
sudo ip tuntap add user $USERID mode tap
postcreation=$(ip tuntap list | cut -d: -f1 | sort)
TAP=$(comm -13 <(echo "$precreationg") <(echo "$postcreation"))
nicbr0 $TAP

printf -v MACADDR "52:54:%02x:%02x:%02x:%02x" $(( $RANDOM & 0xff)) $(( $RANDOM & 0xff )) $(( $RANDOM & 0xff)) $(( $RANDOM & 0xff ))
qemu-system-x86_64 -net nic,macaddr=$MACADDR,model=virtio \
    -net tap,ifname=$TAP,script=no,downscript=no,vhost=on \
    $@

_nicbr0 $TAP
sudo ip link set dev $TAP down &> /dev/null
sudo ip tuntap del $TAP mode tap

if [ -z $HASBR0 ] ; then
    _nicbr0 $NIC
    sudo ip addr del dev br0 $IPADDR/24 &> /dev/null
    sudo ip link set dev br0 down
    sudo ip link delete br0 type bridge &> /dev/null
    sudo ip route del default &> /dev/null
    sudo ip link set dev $NIC up
    sudo ip route add default via $ROUTER dev $NIC onlink &> /dev/null
fi

それから VM を起動するために、以下のようにコマンドを実行して下さい:

$ run-qemu -hda myvm.img -m 512
/etc/sysctl.d/10-disable-firewall-on-bridge.conf
net.bridge.bridge-nf-call-ip6tables = 0
net.bridge.bridge-nf-call-iptables = 0
net.bridge.bridge-nf-call-arptables = 0

すぐに変更を適用するには sysctl -p /etc/sysctl.d/10-disable-firewall-on-bridge.conf を実行してください。

libvirt wikiFedora bug 512206 を参照。起動中にファイルが存在しないというエラーが起こるときは、起動時に bridge モジュールをロードするようにしてください。カーネルモジュール#ロード を参照。

または、次のようにルールを追加することで全てのトラフィックをブリッジで通すように iptables を設定することができます:

-I FORWARD -m physdev --physdev-is-bridged -j ACCEPT

Network sharing between physical device and a Tap device through iptables

この記事あるいはセクションは インターネット共有 と合併することが議論されています。
ノート: Duplication, not specific to QEMU. (議論: トーク:QEMU#)

Bridged networking works fine between a wired interface (Eg. eth0), and it is easy to setup. However if the host gets connected to the network through a wireless device, then bridging is not possible.

See ネットワークブリッジ#ブリッジ上の無線インターフェイス as a reference.

One way to overcome that is to setup a tap device with a static IP, making linux automatically handle the routing for it, and then forward traffic between the tap interface and the device connected to the network through iptables rules.

See インターネット共有 as a reference.

There you can find what is needed to share the network between devices, included tap and tun ones. The following just hints further on some of the host configurations required. As indicated in the reference above, the client needs to be configured for a static IP, using the IP assigned to the tap interface as the gateway. The caveat is that the DNS servers on the client might need to be manually edited if they change when changing from one host device connected to the network to another.

To allow IP forwarding on every boot, one need to add the following lines to sysctl configuration file inside /etc/sysctl.d:

net.ipv4.ip_forward = 1
net.ipv6.conf.default.forwarding = 1
net.ipv6.conf.all.forwarding = 1

The iptables rules can look like:

# Forwarding from/to outside
iptables -A FORWARD -i ${INT} -o ${EXT_0} -j ACCEPT
iptables -A FORWARD -i ${INT} -o ${EXT_1} -j ACCEPT
iptables -A FORWARD -i ${INT} -o ${EXT_2} -j ACCEPT
iptables -A FORWARD -i ${EXT_0} -o ${INT} -j ACCEPT
iptables -A FORWARD -i ${EXT_1} -o ${INT} -j ACCEPT
iptables -A FORWARD -i ${EXT_2} -o ${INT} -j ACCEPT
# NAT/Masquerade (network address translation)
iptables -t nat -A POSTROUTING -o ${EXT_0} -j MASQUERADE
iptables -t nat -A POSTROUTING -o ${EXT_1} -j MASQUERADE
iptables -t nat -A POSTROUTING -o ${EXT_2} -j MASQUERADE

The prior supposes there are 3 devices connected to the network sharing traffic with one internal device, where for example:

INT=tap0
EXT_0=eth0
EXT_1=wlan0
EXT_2=tun0

The prior shows a forwarding that would allow sharing wired and wireless connections with the tap device.

The forwarding rules shown are stateless, and for pure forwarding. One could think of restricting specific traffic, putting a firewall in place to protect the guest and others. However those would decrease the networking performance, while a simple bridge does not include any of that.

Bonus: Whether the connection is wired or wireless, if one gets connected through VPN to a remote site with a tun device, supposing the tun device opened for that connection is tun0, and the prior iptables rules are applied, then the remote connection gets also shared with the guest. This avoids the need for the guest to also open a VPN connection. Again, as the guest networking needs to be static, then if connecting the host remotely this way, one most probably will need to edit the DNS servers on the guest.

VDE2 によるネットワーク

VDE とは?

VDE は Virtual Distributed Ethernet の略です。uml_switch の拡張として始まりました。仮想ネットワークを管理するためのツールボックスです。

基本的にはソケットである仮想スイッチを作成して、物理マシンと仮想マシンを両方ともスイッチに"接続"するという考えになります。以下で説明する設定はとてもシンプルです。ただし、VDE はさらに強力な力を持っており、仮想スイッチ同士を接続したり、別のホストでスイッチを動作させスイッチのトラフィックを監視することなどができます。プロジェクトのドキュメント を読むことを推奨。

この方法の利点はユーザーに sudo 権限を与える必要がないということです。通常ユーザーに modprobe の実行を許可する必要はありません。

基本

VDE サポートは vde2 パッケージでインストールできます。

この設定では、tun/tap を使ってホストに仮想インターフェイスを作成します。tun モジュールをロード (詳しくはカーネルモジュールを参照):

# modprobe tun

仮想スイッチを作成:

# vde_switch -tap tap0 -daemon -mod 660 -group users

上記のコマンドでスイッチと tap0 が作成され、接続され、そして users グループのユーザーがスイッチを使えるようにします。

インターフェイスは接続されてもまだ設定がされていません。設定するには、次のコマンドを実行:

# ip addr add 192.168.100.254/24 dev tap0

そして、通常ユーザーで -net オプションを使って KVM を実行してください:

$ qemu-system-x86_64 -net nic -net vde -hda [...]

物理ネットワークでやるのと同じようにゲストのネットワークを設定してください。

ヒント: 仮想マシンからインターネットにアクセスするためにタップデバイスに NAT を設定することができます。詳しくはインターネット共有#NAT の有効化を見て下さい。

起動スクリプト

VDE を起動するメインスクリプトの例:

/etc/systemd/scripts/qemu-network-env
#!/bin/sh
# QEMU/VDE network environment preparation script

# The IP configuration for the tap device that will be used for
# the virtual machine network:

TAP_DEV=tap0
TAP_IP=192.168.100.254
TAP_MASK=24
TAP_NETWORK=192.168.100.0

# Host interface
NIC=eth0

case "$1" in
  start)
        echo -n "Starting VDE network for QEMU: "

        # If you want tun kernel module to be loaded by script uncomment here 
	#modprobe tun 2>/dev/null
	## Wait for the module to be loaded
 	#while ! lsmod | grep -q "^tun"; do echo "Waiting for tun device"; sleep 1; done

        # Start tap switch
        vde_switch -tap "$TAP_DEV" -daemon -mod 660 -group users

        # Bring tap interface up
        ip address add "$TAP_IP"/"$TAP_MASK" dev "$TAP_DEV"
        ip link set "$TAP_DEV" up

        # Start IP Forwarding
        echo "1" > /proc/sys/net/ipv4/ip_forward
        iptables -t nat -A POSTROUTING -s "$TAP_NETWORK"/"$TAP_MASK" -o "$NIC" -j MASQUERADE
        ;;
  stop)
        echo -n "Stopping VDE network for QEMU: "
        # Delete the NAT rules
        iptables -t nat -D POSTROUTING "$TAP_NETWORK"/"$TAP_MASK" -o "$NIC" -j MASQUERADE

        # Bring tap interface down
        ip link set "$TAP_DEV" down

        # Kill VDE switch
        pgrep -f vde_switch | xargs kill -TERM 
        ;;
  restart|reload)
        $0 stop
        sleep 1
        $0 start
        ;;
  *)
        echo "Usage: $0 {start|stop|restart|reload}"
        exit 1
esac
exit 0

上のスクリプトを使う systemd サービスの例:

/etc/systemd/system/qemu-network-env.service
[Unit]
Description=Manage VDE Switch

[Service]
Type=oneshot
ExecStart=/etc/systemd/scripts/qemu-network-env start
ExecStop=/etc/systemd/scripts/qemu-network-env stop
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

qemu-network-env が実行できるようにパーミッションを変更:

# chmod u+x /etc/systemd/scripts/qemu-network-env

通常の方法で起動することができます (詳しくは systemd#ユニットを使う を参照):

# systemctl start qemu-network-env

他の方法

上の方法が動作しない場合やカーネル設定, TUN, dnsmasq, iptables を変えたくない場合は以下のコマンドで同じ結果になります。

# vde_switch -daemon -mod 660 -group users
# slirpvde --dhcp --daemon

ホストのネットワークの接続を使って VM を起動するには:

$ qemu-system-x86_64 -net nic,macaddr=52:54:00:00:EE:03 -net vde disk_image

VDE2 Bridge

quickhowto: qemu networking using vde, tun/tap, and bridge に基づいています。vde に接続された仮想マシンは外部から参照出来る状態になります。例えば、ADSL ルーターから直接 DHCP の設定を個々の仮想マシンが受け取ることが可能です。

基本

tun モジュールと bridge-utils パッケージが必要です。

vde2/tap デバイスを作成:

# vde_switch -tap tap0 -daemon -mod 660 -group users
# ip link set tap0 up

ブリッジを作成:

# brctl addbr br0

デバイスを追加:

# brctl addif br0 eth0
# brctl addif br0 tap0

ブリッジインターフェイスを設定:

# dhcpcd br0

起動スクリプト

全てのデバイスを設定する必要があります。ブリッジに必要なのは IP アドレスだけです。ブリッジの物理デバイスは (例: eth0)、netctl でカスタム Ethernet プロファイルを使います:

/etc/netctl/ethernet-noip
Description='A more versatile static Ethernet connection'
Interface=eth0
Connection=ethernet
IP=no

以下のカスタム systemd サービスを使うことで users ユーザーグループで使用する VDE2 tap インターフェイスを作成することができます。

/etc/systemd/system/vde2@.service
[Unit]
Description=Network Connectivity for %i
Wants=network.target
Before=network.target

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/bin/vde_switch -tap %i -daemon -mod 660 -group users
ExecStart=/usr/bin/ip link set dev %i up
ExecStop=/usr/bin/ip addr flush dev %i
ExecStop=/usr/bin/ip link set dev %i down

[Install]
WantedBy=multi-user.target

そして最後に、netctl でブリッジネットワークを作成することが可能です。

省略記法

QEMU をさまざまなネットワーク・オプションとともに頻繁に使用している場合、-netdev-device の引数のペアを大量に作成している可能性があり、かなり反復的になっています。代わりに -nic 引数を使って、 -netdev-device を結合することもできます。たとえば、次のような引数は:

-netdev tap,id=network0,ifname=tap0,script=no,downscript=no,vhost=on-device virtio-net-pci,netdev=network0

こうなります:

-nic tap,script=no,downscript=no,vhost=on,model=virtio-net-pci

ネットワーク ID がないこと、およびデバイスが model= で作成されたことに注意してください。-nic パラメータの前半は -netdev パラメータですが、後半 (model= の後) はデバイスに関連付けられています。同じパラメータ (たとえば、 smb= ) が使用されます。ネットワークを完全に無効にするには、 -nic none を使用します。

使用できるパラメーターの詳細については、 QEMU ネットワークのドキュメント を参照してください。

グラフィック

QEMU は -curses コマンド・ライン・オプションを使用して、標準のグラフィックカードのテキストモードをエミュレートできます。これにより、テキストターミナル内でテキストを入力しテキスト出力を直接見ることができます。代わりに、 -nographic も同様の目的を果たします。

QEMU はいくつかのタイプの VGA カードをエミュレートできます。カードタイプは -vgatype コマンドラインオプションで渡され、 std, qxl, vmware, virtio, cirrus または none のいずれかになります。

std

-vga std では 2560 x 1600 ピクセルまでの解像度を得ることができます。QEMU 2.2 からデフォルトとなっています。

qxl

QXL は 2D サポートのある準仮想化グラフィックドライバーです。使用するには -vga qxl オプションを使用してゲストにドライバーをインストールしてください。QXL を使用する場合 SPICE を使うことでグラフィックの性能を向上させることができます。

Linux ゲストでは、パフォーマンスを得るために qxlbochs_drm カーネルモジュールをロードしてください。

SPICE

Spice プロジェクト は仮想化されたデスクトップデバイスを操作するための完全な、オープンソースのソリューションを提供することを目的としています。主として QEMU 仮想マシンへの高品質なリモートアクセスを提供することに力を注いでいます。

グラフィック出力に QXL を使用している場合にのみ SPICE を利用できます。

リモートデスクトッププロトコルとして SPICE を使用して起動するコマンドの例:

$ qemu-system-x86_64 -vga qxl -spice port=5930,disable-ticketing -device virtio-serial-pci -device virtserialport,chardev=spicechannel0,name=com.redhat.spice.0 -chardev spicevmc,id=spicechannel0,name=vdagent

-device virtio-serial-pci オプションは virtio-serial デバイスを追加し、-device virtserialport,chardev=spicechannel0,name=com.redhat.spice.0 は spice vdagent のためにデバイスのポートを開いて -chardev spicevmc,id=spicechannel0,name=vdagent はポートに spicevmc chardev を追加します。virtserialport デバイスの chardev= オプションは chardev オプションに指定する id= オプションと一致している必要があります (上記の例では spicechannel0)。また、ポートの名前はゲストの vdagent が使用する名前空間である com.redhat.spice.0 でなければなりません。最後に name=vdagent を指定することで spice はチャンネルの利用目的を使用することができます。

ヒント: SPICE モードの QEMU はリモートデスクトップサーバーのように振る舞うため、-daemonize パラメータを付けて QEMU をデーモンモードで起動するとより便利です。

それから SPICE クライアントでゲストに接続してください。プロトコルの開発者は SPICE クライアントとして virt-viewer を推奨しています:

$ remote-viewer spice://127.0.0.1:5930

リファレンス・テスト実装である spice-gtk3[リンク切れ: 置換パッケージ: spice-gtk] を使うこともできおます:

$ spicy -h 127.0.0.1 -p 5930

クライアントは他にも存在します [2]

TCP ポートの代わりに Unix ソケットを使用することで、パフォーマンスが向上するという報告があります [3]。例:

$ qemu-system-x86_64 -vga qxl -device virtio-serial-pci -device virtserialport,chardev=spicechannel0,name=com.redhat.spice.0 -chardev spicevmc,id=spicechannel0,name=vdagent -spice unix,addr=/tmp/vm_spice.socket,disable-ticketing

接続するには:

$ remote-viewer spice+unix:///tmp/vm_spice.socket

または:

$ spicy --uri="spice+unix:///tmp/vm_spice.socket"

マルチモニターやクリップボードの共有などのサポートが必要な場合、以下のパッケージをゲスト側でインストールしてください:

インストールしたら spice-vdagentd.service を有効にしてください。

SPICE によるパスワード認証

SPICE のパスワード認証を有効にしたい場合、-spice 引数から disable-ticketing を外して password=yourpassword を追加してください。例:

$ qemu-system-x86_64 -vga qxl -spice port=5900,password=yourpassword -device virtio-serial-pci -device virtserialport,chardev=spicechannel0,name=com.redhat.spice.0 -chardev spicevmc,id=spicechannel0,name=vdagent

SPICE サーバーに接続する際に SPICE クライアントがパスワードを要求するようになります。

TLS 暗号化

SPICE サーバーとの通信を TLS で暗号化するよう設定することもできます。まず、以下のファイルが含まれたディレクトリが必要です (ファイルの名前は完全に一致している必要があります):

  • ca-cert.pem: CA マスター証明書。
  • server-cert.pem: ca-cert.pem で署名されたサーバー証明書。
  • server-key.pem: サーバー秘密鍵。

サーバー自身の CA で自己署名証明書を生成する方法は Spice User Manual に例が載っています。

証明書を用意したら -spice 引数を使って SPICE で QEMU を起動してください: -spice tls-port=5901,password=yourpassword,x509-dir=/path/to/pki_certs (/path/to/pki_certs は証明書が含まれているディレクトリのパスに置き換えてください)。

起動したら virt-viewer を使ってサーバーに接続することが可能です:

$ remote-viewer spice://hostname?tls-port=5901 --spice-ca-file=/path/to/ca-cert.pem --spice-host-subject="C=XX,L=city,O=organization,CN=hostname" --spice-secure-channels=all

--spice-host-subject パラメータは server-cert.pem のサブジェクトにあわせて設定する必要があります。また、サーバー証明書を検証するために ca-cert.pem をクライアントにコピーしてください。

ヒント: --spice-host-subject に指定するサーバー証明書のサブジェクトは以下のコマンドで確認することができます:
$ openssl x509 -noout -subject -in server-cert.pem | cut -d' ' -f2- | sed 's/\///' | sed 's/\//,/g'

spice-gtk3[リンク切れ: 置換パッケージ: spice-gtk] を使用する場合:

$ spicy -h hostname -s 5901 --spice-ca-file=ca-cert.pem --spice-host-subject="C=XX,L=city,O=organization,CN=hostname" --spice-secure-channels=all

vmware

多少バグが存在しますが、std や cirrus よりもパフォーマンスが上です。ゲストに、VMware ドライバーをインストールしてください (Arch Linux ゲストなら xf86-video-vmwarexf86-input-vmmouse)。

virtio

virtio-vga / virtio-gpuvirgl がベースの順仮想化 3D グラフィックドライバーです。発展途上であり、カーネルバージョンが新しい (4.4 以上) Linux ゲストで --with-gallium-drivers=virgl オプションを付けてコンパイルされた mesa (>=11.2) でしか動作しません。

ゲスト環境で 3D アクセラレーションを有効にするには -vga virtio を使って vga を選択して -display sdl,gl=on (sdl ディスプレイ出力) または -display gtk,gl=on (gtk ディスプレイ出力) を使用してディスプレイデバイスで opengl コンテキストを有効にしてください。ゲスト側のカーネルログを見ることで設定が問題ないか確認できます:

$ dmesg | grep drm 
[drm] pci: virtio-vga detected
[drm] virgl 3d acceleration enabled

2016年9月現在、spice プロトコルのサポートは開発中で、spice (>= 0.13.2) の開発版をインストールして qemu を再コンパイルすることでテストできます。

詳しくは kraxel のブログ を見てください。

cirrus

cirrus グラフィカルアダプタは 2.2 以前まではデフォルト でした。新しいシステムでは 使用しないほうがよい とされています。

none

これは VGA カードが全くない PC と同じようになります。-vnc オプションを使ってもアクセスすることはできません。また、QEMU に VGA カードをエミュレートさせ SDL ディスプレイを無効にする -nographic オプションとは異なります。

vnc

-nographic オプションを使っている場合、-vnc display オプションを追加することで QEMU に display を listen させて VGA ディスプレイを VNC セッションにリダイレクトさせることができます。#ブート時に QEMU 仮想マシンを起動する セクションの設定例にこれのサンプルがあります。

$ qemu-system-x86_64 -vga std -nographic -vnc :0
$ gvncviewer :0

VNC を使う際、ここで示されているようなキーボードの問題が発生するかもしれません。解決方法は、QEMU で -k オプションを使わないことと、gtk-vncgvncviewer を使うことです。libvirt のメーリングリストに投稿された この メッセージも参照してください。

オーディオ

ホスト

QEMU で使用するオーディオドライバーは QEMU_AUDIO_DRV 環境変数で設定できます:

$ export QEMU_AUDIO_DRV=pa

以下のコマンドを実行すると PulseAudio に関する QEMU の設定オプションが表示されます:

$ qemu-system-x86_64 -audio-help | awk '/Name: pa/' RS=

表示されたオプションは以下のように環境変数としてエクスポートできます:

$ export QEMU_PA_SINK=alsa_output.pci-0000_04_01.0.analog-stereo.monitor
$ export QEMU_PA_SOURCE=input

ゲスト

使用できるエミュレーションオーディオドライバーのリストを表示するには:

$ qemu-system-x86_64 -soundhw help

例えば、ゲストで hda ドライバーを使用するには -soundhw hda を使ってください。

ノート: ゲストマシンのエミュレートされたビデオグラフィックカードドライバーによって問題が起こることがあります。ドライバーをそれぞれ試してみてください。qemu-system-x86_64 -h | grep vga で利用可能なオプションを確認できます。

virtio ドライバーのインストール

QEMU にで virtio ドライバーを使って準仮想化ブロックとネットワークデバイスをゲストが利用できるようにすることができ、より良いパフォーマンス・少ないオーバーヘッドを実現します。

  • virtio ブロックデバイスにはシンプルな -hd* の代わりに -drive オプションと if=virtio が必要です:
$ qemu-system-x86_64 -boot order=c -drive file=disk_image,if=virtio
ノート: 起動するには -boot order=c が絶対に必要です。-hd* では自動で検出されません。
  • ネットワークでもほぼ同じです:
$ qemu-system-x86_64 -net nic,model=virtio
ノート: ゲストマシンに virtio デバイスのドライバーが存在する場合にのみ機能します。Arch Linux を含む Linux には必要なドライバーが入っていますが、他のオペレーティングシステムで virtio デバイスが使える保証はありません。

(Arch) Linux ゲストを用意する

Arch Linux ゲストをインストールした後 virtio デバイスを使うには、次のモジュールをゲストでロードする必要があります: virtio, virtio_pci, virtio_blk, virtio_net, virtio_ring。32ビットのゲストの場合、特定の "virtio" モジュールは必要ありません。

virtio ディスクから起動したい場合、イニシャル RAM ディスクに必要なモジュールを含ませなければなりません。デフォルトでは、mkinitcpioautodetect フックによって管理されています。もしくは /etc/mkinitcpio.confMODULES 行を使って必要なモジュールを含めてイニシャル RAM ディスクをリビルドしてください。

/etc/mkinitcpio.conf
MODULES="virtio virtio_blk virtio_pci virtio_net"

Virtio ディスクは前に v が付いて認識されます (例: vda, vdb など)。なので、virtio ディスクから起動する際は /etc/fstab/boot/grub/grub.cfg などに変更を加える必要があります。

ヒント: /etc/fstab とブートローダーの両方で UUID を使ってディスクを指定している場合、何もする必要はありません。

KVM による準仮想化に関する詳細は こちら で読むことができます。

qemu-guest-agent をインストールすることでハイパーバイザの管理機能を拡張する QMP コマンドのサポートを得ることができます。パッケージをインストールしたら qemu-ga.service を起動・有効化してください。

Windows ゲストを用意する

ノート: Windows 8.1 ゲストを Windows 10 にアップグレードするには、一時的に CPU を core2duo,nx にしてインストールするしかありません [4]。インストール後は他の CPU 設定に戻して大丈夫です。

ブロックデバイスドライバー

Windows の新規インストール

Windows には virtio ドライバーが付属していません。そのため、インストール時にロードする必要があります。基本的には2つの方法が存在します: フロッピーディスクを使用するか ISO ファイルを使用するかです。どちらのイメージも Fedora のリポジトリ からダウンロードできます。

フロッピーディスクを使う方法は QEMU の電源を入れた最初のときに F6 (新しい Windows では Shift-F6) を押さなければいけないため難易度が高くなります。VNC コンソールウィンドウに接続するのに時間が必要であるためです。起動シーケンスに遅延時間を追加することができます。起動時に遅延を適用する方法は qemu(1) を参照してください。

ISO を使ってドライバーをロードする方法は Windows Vista あるいは Windows Server 2008 以降でないと使用できません。virtio ドライバーでイメージをロードして、それから最初のディスクデバイスで cdrom デバイスと Windows インストーラーをロードします:

$ qemu-system-x86_64 ... \
-drive file=/path/to/primary/disk.img,index=0,media=disk,if=virtio \
-drive file=/path/to/installer.iso,index=2,media=cdrom \
-drive file=/path/to/virtio.iso,index=3,media=cdrom \
...

インストール時に Windows インストーラーはプロダクトキーを要求してチェックを行います。"Where do you want to install Windows?" 画面では、ディスクが見つけられないという警告が表示されます。以下の手順に従ってください (アップデート適用済みの Windows Server 2012 R2 がベース):

  • Load Drivers オプションを選択。
  • "Hide drivers that aren't compatible with this computer's hardware" のチェックを外す。
  • Browse ボタンをクリックして virtio iso の CDROM を開く (通常は "virtio-win-XX" という名前になります)。
  • E:\viostor\[your-os]\amd64 を選択して OK を押す。
  • Next をクリック。

これで virtio ディスクが表示されるので、選択して、フォーマット・インストールすることができます。

virtio を使用するように既存の Windows 仮想マシンを変更

virtio ディスクから起動するように Windows ゲストを用意するのはやや面倒です。

Fedora のリポジトリ から virtio ディスクドライバーをダウンロードすることができます。

そして Windows がドライバーを検索するように、新しいディスクイメージを作成する必要があります。例:

$ qemu-img create -f qcow2 fake.qcow2 1G

(virtio モードの) フェイクディスクと CD-ROM とドライバーで元の Windows ゲストを起動 (ブートディスクを IDE モードで使う):

$ qemu-system-x86_64 -m 512 -vga std -drive file=windows_disk_image,if=ide -drive file=fake.qcow2,if=virtio -cdrom virtio-win-0.1-81.iso

Windows はフェイクディスクを検出してそのドライバーを検索します。ドライバーが見つからない場合は、Device Manager を開いて、エクスクラメーションマークのアイコンが付いた SCSI ドライブを探して (開いて下さい)、Update driver をクリックして仮想 CD-ROM を選択してください。ディレクトリを再帰的に検索すると書かれたチェックボックスを選択するのを忘れずに。

インストールが成功したら、仮想マシンを止めて virtio モードのブートディスクで再起動することができます:

$ qemu-system-x86_64 -m 512 -vga std -drive file=windows_disk_image,if=virtio
ノート: ブルースクリーンになってしまう場合は、-m パラメータを忘れていないこと、ドライバーをインストールする前にシステムドライブを ide ではなく virtio を使って起動していないことを確認してください。

ネットワークドライバー

virtio ネットワークドライバーのインストールはもう少し簡単で、上記に -net 引数を追加します:

$ qemu-system-x86_64 -m 512 -vga std -drive file=windows_disk_image,if=virtio -net nic,model=virtio -cdrom virtio-win-0.1-74.iso

Windows はネットワークアダプタを検出してそのドライバーを検索します。ドライバーが見つからない場合は、Device Manager を開いて、エクスクラメーションマークのアイコンが付いたネットワークアダプタを探して (開いて下さい)、Update driver をクリックして仮想 CD-ROM を選択してください。ディレクトリを再帰的に検索すると書かれたチェックボックスを選択するのを忘れずに。

バルーンドライバー

(virsh コマンドの dommemstat を使うなどして) ゲストのメモリ状態を監視したりメモリの容量を実行中に変えたい場合、ゲストバルーンドライバーをインストールする必要があります。

Device Manager を開いて System devicesPCI standard RAM Controller (あるいは Other devices の unrecognized PCI controller) から Update driver を選択してください。ウィンドウが開いたら Browse my computer... を選んで CD-ROM を選択してください (必ず Include subdirectories チェックボックスにチェックを入れてください)。インストールしたら再起動してください。ドライバーがインストールされてバルーンを膨張させることができるようになります (例えば hmp の balloon memory_size コマンドでバルーンができるかぎり多くのメモリを取得してゲストの利用可能なメモリ容量を memory_size まで縮小します)。ただしゲストのメモリ状態を監視するには、さらに Balloon サービスをインストールする必要があります。管理者としてコマンドラインを開いて CD-ROM から Balloon ディレクトリの奥に入ってください。amd64 (x86) ディレクトリまで入ったら blnsrv.exe -i を実行することでインストールが実行されます。その後 virshdommemstat コマンドでサポートされている値が出力されるはずです。

FreeBSD ゲストを用意する

FreeBSD 8.3 以降を使っている場合は emulators/virtio-kmod port をインストールしてください、10.0-CURRENT ではカーネルに含まれています。インストール後、/boot/loader.conf ファイルに以下を追加します:

virtio_loader="YES"
virtio_pci_load="YES"
virtio_blk_load="YES"
if_vtnet_load="YES"
virtio_balloon_load="YES"

そして次を実行して /etc/fstab を修正してください:

sed -i bak "s/ada/vtbd/g" /etc/fstab

それから /etc/fstab が問題ないか確認してください。何かがおかしい場合、レスキュー CD で起動して /etc/fstab.bak/etc/fstab にコピーします。

QEMU モニタ

QEMU の実行中、仮想マシンを操作するためのモニタコンソールが表示されます。QEMU モニタには仮想マシンの情報を取得したりデバイスをホットプラグしたり、仮想マシンの状態を保存するスナップショットを作成するなどの機能があります。利用可能なコマンドのリストは QEMU モニタコンソールで help または ? を実行したり、QEMU 公式ドキュメント で確認できます。

モニタコンソールにアクセス

デフォルトグラフィックオプションの std を使用している場合、QEMU ウィンドウで Ctrl+Alt+2 を押すか View > compatmonitor0 をクリックすることで QEMU モニタにアクセスできます。仮想マシンのグラフィックビューに戻るには Ctrl+Alt+1 を押すか View > VGA をクリックします。

ただし、モニタにアクセスする標準の方法は QEMU がサポートしている全てのグラフィック出力で使えるわけではありません。モニタにアクセスする別の方法として以下の方法があります:

  • telnet: -monitor telnet:127.0.0.1:port,server,nowait パラメータを付けて QEMU を起動してください。仮想マシンが起動したら telnet 経由でモニタにアクセスできます:
$ telnet 127.0.0.1 port
ノート: listen する IP として 127.0.0.1 を指定した場合、QEMU が動作している同一ホストからのみモニタに接続できるようになります。リモートホストから接続したい場合、QEMU が 0.0.0.0 を listen するように指定する必要があります: -monitor telnet:0.0.0.0:port,server,nowait。接続は暗号化されず認証も不要であるため、ファイアウォールが設定されていてローカルネットワークが信頼できる場合のみこの方法を使ってください。
  • UNIX ソケット: -monitor unix:socketfile,server,nowait パラメータを付けて QEMU を起動してください。socat または openbsd-netcat を使って接続することができます。

例えば QEMU を以下のコマンドで起動した場合:

$ qemu-system-x86_64 [...] -monitor unix:/tmp/monitor.sock,server,nowait [...]

以下のコマンドでモニタに接続できます:

$ socat - UNIX-CONNECT:/tmp/monitor.sock

または:

$ nc -U /tmp/monitor.sock
  • TCP: -monitor tcp:127.0.0.1:port,server,nowait パラメータを付けることで TCP 経由でモニタにアクセスできます。openbsd-netcat または gnu-netcat をインストールして netcat で接続してください:
$ nc 127.0.0.1 port
ノート: QEMU が動作しているホスト以外のデバイスから tcp ソケットに接続したい場合、telnet と同じように 0.0.0.0 を使うようにしてください。
  • 標準 I/O: -monitor stdio 引数を付けて起動することで同じターミナルから自動的にモニタにアクセスすることができます。

モニタコンソールを使って仮想マシンにキーボードの押下を送信

設定によっては仮想マシン上で一部のキーの組み合わせがホストによって邪魔されて使えない場合があります (tty を切り替える Ctrl+Alt+F* など)。特定のキーの組み合わせについてはモニタコンソールを使ってキーを送信することで問題を解決できます。モニタに切り替えてから sendkey コマンドを使って仮想マシンにキーの押下を送信してください。例:

(qemu) sendkey ctrl-alt-f2

モニタコンソールを使ってスナップショットを作成・管理

ノート: スナップショット機能は仮想マシンのディスクイメージが qcow2 形式の場合にのみ利用できます。raw イメージでは使用できません。

ときには仮想マシンの現在の状態を保存して何か問題が発生したときに仮想マシンの状態を元に戻したいということもあるでしょう。QEMU のモニタコンソールにはスナップショットを作成・管理してマシンの状態をリバートするのに必要なユーティリティが備わっています。

  • savevm name を使うことで name という名前のスナップショットが作成されます。
  • loadvm name をしよすうると仮想マシンがスナップショット name の状態に戻ります。
  • delvm namename という名前のスナップショットが削除されます。
  • 保存済みのスナップショットのリストは info snapshots で確認できます。スナップショットは自動付与される ID 番号とユーザーがスナップショットを作成するときに付けた名前で識別できます。

immutable モードで仮想マシンを起動

-snapshot パラメータを付けて QEMU を起動することで仮想マシンを凍った状態で実行することができ、仮想マシンの電源が来られたときに全ての変更は破棄されます。ゲストによるディスクイメージの書き込みがあったときは、/tmp の一時ファイルに変更が保存され QEMU が停止したときに消去されます。

ただしマシンが frozen モードで実行中のとき、モニタコンソールを使って以下のコマンドを実行することで変更をディスクイメージに保存することが可能です:

(qemu) commit

frozen モードで実行中にスナップショットが作成されると同じようにディスクに変更をコミットしないかぎり QEMU の終了時に破棄されます。

モニタコンソールによる一時停止と電源オプション

モニタコマンドを使って物理マシンの操作を QEMU でエミュレートできます:

  • system_powerdown は仮想マシンに ACPI シャットダウンリクエストを送信します。物理マシンの電源ボタンを押したときと同じような動きになります。
  • system_reset は物理マシンのリセットボタンと同じように仮想マシンをリセットします。仮想マシンが正常に再起動されないためデータが消失したりファイルシステムが破損する可能性があります。
  • stop は仮想マシンを停止します。
  • cont は仮想マシンを停止した状態から復帰します。

仮想マシンのスクリーンショットの取得

モニタコンソールで以下のコマンドを実行することで PPM 形式で仮想マシンのグラフィックディスプレイのスクリーンショットを取得できます:

(qemu) screendump file.ppm

ヒントとテクニック

Improve virtual machine performance

There are a number of techniques that you can use to improve the performance of the virtual machine. For example:

  • Apply #Enabling KVM for full virtualization.
  • Use the -cpu host option to make QEMU emulate the host's exact CPU rather than a more generic CPU.
  • Especially for Windows guests, enable Hyper-V enlightenments: -cpu host,hv_relaxed,hv_spinlocks=0x1fff,hv_vapic,hv_time.
  • If the host machine has multiple cores, assign the guest more cores using the -smp option.
  • Make sure you have assigned the virtual machine enough memory. By default, QEMU only assigns 128 MiB of memory to each virtual machine. Use the -m option to assign more memory. For example, -m 1024 runs a virtual machine with 1024 MiB of memory.
  • If supported by drivers in the guest operating system, use virtio for network and/or block devices, see #Installing virtio drivers.
  • Use TAP devices instead of user-mode networking, see #Tap networking with QEMU.
  • If the guest OS is doing heavy writing to its disk, you may benefit from certain mount options on the host's file system. For example, you can mount an ext4 file system with the option barrier=0. You should read the documentation for any options that you change because sometimes performance-enhancing options for file systems come at the cost of data integrity.
  • If you have a raw disk image, you may want to disable the cache:
    $ qemu-system-x86_64 -drive file=disk_image,if=virtio,cache=none
  • Use the native Linux AIO:
    $ qemu-system-x86_64 -drive file=disk_image,if=virtio,aio=native,cache.direct=on
  • If you are running multiple virtual machines concurrently that all have the same operating system installed, you can save memory by enabling kernel same-page merging. See #Enabling KSM.
  • In some cases, memory can be reclaimed from running virtual machines by running a memory ballooning driver in the guest operating system and launching QEMU using -device virtio-balloon.
  • It is possible to use a emulation layer for an ICH-9 AHCI controller (although it may be unstable). The AHCI emulation supports NCQ, so multiple read or write requests can be outstanding at the same time:
    $ qemu-system-x86_64 -drive id=disk,file=disk_image,if=none -device ich9-ahci,id=ahci -device ide-drive,drive=disk,bus=ahci.0

See https://www.linux-kvm.org/page/Tuning_KVM for more information.

ブート時に QEMU 仮想マシンを起動する

libvirt を使う

libvirt を使って仮想マシンをセットアップした場合、virsh autostart や virt-manager の GUI を通して、仮想マシンの Boot Options から "Start virtual machine on host boot up" を選択することでホストの起動時に仮想マシンを起動するように設定することができます。

カスタムスクリプト

起動時に QEMU VM を実行するように、以下の systemd ユニットと設定を使うことができます。

/etc/systemd/system/qemu@.service
[Unit]
Description=QEMU virtual machine

[Service]
Environment="type=system-x86_64" "haltcmd=kill -INT $MAINPID"
EnvironmentFile=/etc/conf.d/qemu.d/%i
PIDFile=/tmp/%i.pid
ExecStart=/usr/bin/env qemu-${type} -name %i -nographic -pidfile /tmp/%i.pid $args
ExecStop=/bin/sh -c ${haltcmd}
TimeoutStopSec=30
KillMode=none

[Install]
WantedBy=multi-user.target
ノート:
  • systemd.service(5)systemd.kill(5) の man ページによれば、KillMode=none オプションの使用が必須です。このオプションがないと ExecStop コマンド (一行 echo するだけ) が終了した後にすぐにメインの qemu プロセスがキルされることになり、システムを正しくシャットダウンできなくなってしまいます。
  • PIDFile オプションを使用しないと systemd は qemu のメインプロセスが終了したかどうか通知できず、システムが正しくシャットダウンできなくなります。ホスト環境でシャットダウンしても仮想マシンのシャットダウンを待機しなくなってしまいます。

VM ごとに、/etc/conf.d/qemu.d/vm_name という名前の設定ファイルを作成して、以下の変数を設定します:

type
実行する QEMU バイナリ。指定すれば、/usr/bin/qemu- が前に付けられて VM を起動するのにそのバイナリが使われます。例えば type="system-arm"qemu-system-arm イメージが起動できます。
args
起動するときの QEMU コマンドライン。-name ${vm} -nographic はいつも前に付けます。
haltcmd
VM を安全にシャットダウンするためのコマンド。例えば -monitor telnet:.. を使ってモニターに system_powerdown を送信して ACPI で VM の電源を切ります。SSH やその他の方法が使えます。

設定例:

/etc/conf.d/qemu.d/one
type="system-x86_64"

args="-enable-kvm -m 512 -hda /dev/mapper/vg0-vm1 -net nic,macaddr=DE:AD:BE:EF:E0:00 \
 -net tap,ifname=tap0 -serial telnet:localhost:7000,server,nowait,nodelay \
 -monitor telnet:localhost:7100,server,nowait,nodelay -vnc :0"

haltcmd="echo 'system_powerdown' | nc localhost 7100" # or netcat/ncat

# You can use other ways to shut down your VM correctly
#haltcmd="ssh powermanager@vm1 sudo poweroff"
/etc/conf.d/qemu.d/two
args="-enable-kvm -m 512 -hda /srv/kvm/vm2.img -net nic,macaddr=DE:AD:BE:EF:E0:01 \
 -net tap,ifname=tap1 -serial telnet:localhost:7001,server,nowait,nodelay \
 -monitor telnet:localhost:7101,server,nowait,nodelay -vnc :1"

haltcmd="echo 'system_powerdown' | nc localhost 7101"

以下のコマンドを使って、ブート時にそれぞれの仮想マシンが起動するように設定します:

# systemctl enable qemu@vm_name
# systemctl disable qemu@vm_name

シームレスなマウス

ゲストのオペレーティングシステムのウィンドウをクリックしたときにマウスが取り込まれないようにするには、-usb -device usb-tablet オプションを追加します。これによって QEMU はマウスを取り込むことなくマウスの位置を伝えることができるようになります。また、このコマンドは有効化されている場合 PS/2 マウスエミュレーションを上書きします。例:

$ qemu-system-x86_64 -hda disk_image -m 512 -vga std -usb -device usb-tablet

上のコマンドで動作しない場合は、#マウスカーソルが敏感すぎたり迷走する を参照してみて下さい。

ホスト USB デバイスのパススルー

VM からホストに接続された物理 USB デバイスにアクセスするために、以下のオプションを使って QEMU を起動することができます:

$ qemu-system-x86_64 -usbdevice host:vendor_id:product_id disk_image

lsusb コマンドでデバイスの vendor_idproduct_id がわかります。

デフォルトで qemu によってエミュレートされる I440FX チップセットはシングル UHCI コントローラ (USB 1) のため、-usbdevice オプションは物理デバイスを USB 1 にアタッチしますが新しいデバイスでは場合によっては問題が発生することがあります。-machine type=q35 オプションを使って12個までのデバイスをサポートする EHCI コントローラを提供する ICH9 チップセットをエミュレートさせることで解決します。

-device usb-ehci,id=ehci-device nec-usb-xhci,id=xhci オプションを使って EHCI (USB 2) または XHCI (USB 3) コントローラをエミュレートして以下のように -device usb-host,.. オプションを使って物理デバイスにアタッチするという方法もあります:

-device usb-host,bus=controller_id.0,vendorid=0xvendor_id,productid=0xproduct_id

...,port=<n> 設定を追加することで仮想コントローラの物理ポートを指定することができます。複数の USB デバイスを VM に追加したい場合に有用です。

ノート: QEMU の実行時にパーミッションエラーが起こる場合は、Udev#udev ルールを記述する のデバイスのパーミッションの設定方法を見て下さい。

SPICE による USB リダイレクト

SPICE を使用しているのであれば、QEMU コマンドで指定しなくてもクライアントから仮想マシンに USB デバイスをリダイレクトすることが可能です。USB スロットの数を設定することができます (スロットの数によって同時にリダイレクトできるデバイスの最大数が決まります)。-usbdevice を使用する方法と違って SPICE でリダイレクトする場合は仮想マシンを起動した後に USB デバイスをホットスワップすることができ、リダイレクトから USB デバイスを削除・追加するのに仮想マシンを停止する必要がありません。また、ネットワーク経由でクライアントからサーバーに USB デバイスをリダイレクトすることもできます。QEMU 仮想マシンで USB デバイスを最大限に活用することが可能です。

使用するには USB リダイレクトスロットにそれぞれ EHCI/UHCI コントローラーと SPICE リダイレクトチャンネルを追加する必要があります。例えば、3つの USB スロットをリダイレクトで使用できるように SPICE モードで仮想マシンを起動するには QEMU コマンドに以下の引数を追加します:

-device ich9-usb-ehci1,id=usb \
-device ich9-usb-uhci1,masterbus=usb.0,firstport=0,multifunction=on \
-device ich9-usb-uhci2,masterbus=usb.0,firstport=2 \
-device ich9-usb-uhci3,masterbus=usb.0,firstport=4 \
-chardev spicevmc,name=usbredir,id=usbredirchardev1 \
-device usb-redir,chardev=usbredirchardev1,id=usbredirdev1 \
-chardev spicevmc,name=usbredir,id=usbredirchardev2 \
-device usb-redir,chardev=usbredirchardev2,id=usbredirdev2 \
-chardev spicevmc,name=usbredir,id=usbredirchardev3 \
-device usb-redir,chardev=usbredirchardev3,id=usbredirdev3

spice-gtk3[リンク切れ: 置換パッケージ: spice-gtk]spicy (Input > Select USB Devices for redirection) と virt-viewerremote-viewer (File > USB device selection) の両方ともリダイレクト機能をサポートしています。期待通りに動作させるには仮想マシンに SPICE ゲストツールをインストールする必要があります (詳しくは #SPICE セクションを参照してください)。

警告: クライアントから USB デバイスをリダイレクトしている間は、リダイレクトを停止するまでクライアントのオペレーティングシステムからデバイスを使うことはできなくなるので注意してください。特に入力デバイス (マウスやキーボード) をリダイレクトするときは注意しないと、SPICE のクライアントメニューから戻すことができなくなってしまいます。仮想マシンに入力デバイスをリダイレクトするとクライアントが入力デバイスに反応しなくなるためです。

Automatic USB forwarding with udev

Normally, forwarded devices must be available at VM boot time to be forwarded. If that device is disconnected, it will not be forwarded anymore.

You can use udev rules to automatically attach a device when it comes online. Create a hostdev entry somewhere on disk. chown it to root to prevent other users modifying it.

/usr/local/hostdev-mydevice.xml
<hostdev mode='subsystem' type='usb'>
  <source>
    <vendor id='0x03f0'/>
    <product id='0x4217'/>
  </source>
</hostdev>

Then create a udev rule which will attach/detach the device:

/usr/lib/udev/rules.d/90-libvirt-mydevice
ACTION=="add", \
    SUBSYSTEM=="usb", \
    ENV{ID_VENDOR_ID}=="03f0", \
    ENV{ID_MODEL_ID}=="4217", \
    RUN+="/usr/bin/virsh attach-device GUESTNAME /usr/local/hostdev-mydevice.xml"
ACTION=="remove", \
    SUBSYSTEM=="usb", \
    ENV{ID_VENDOR_ID}=="03f0", \
    ENV{ID_MODEL_ID}=="4217", \
    RUN+="/usr/bin/virsh detach-device GUESTNAME /usr/local/hostdev-mydevice.xml"

Source and further reading.

KSM を有効にする

Kernel Samepage Merging (KSM) はアプリケーションがページをマージするように登録した他のプロセスとページをマージするようにカーネルに登録できるようにする Linux カーネルの機能です。この KSM 機構によってゲストの仮想マシンは互いにページを共有することが可能になります。同じようなゲストオペレーティングシステムが多数動作する環境では、メモリの使用量を著しく節約することができます。

KSM を有効にするには、次を実行してください:

# echo 1 > /sys/kernel/mm/ksm/run

systemd の一時ファイルを使って KSM を永続的に有効にできます:

/etc/tmpfiles.d/ksm.conf
w /sys/kernel/mm/ksm/run - - - - 1

KSM が動作しているとき、マージされるページが存在するために (つまり少なくとも2つの同じような VM が動いている)、/sys/kernel/mm/ksm/pages_shared はゼロになりません。詳しくは https://www.kernel.org/doc/Documentation/vm/ksm.txt を参照。

ヒント: KSM が問題なく動いているか確かめる簡単な方法として、ディレクトリのファイルの中身を全て表示する方法があります:
$ grep . /sys/kernel/mm/ksm/*

マルチモニターのサポート

Linux QXL ドライバーはデフォルトで4台までのマルチモニター (仮想スクリーン) をサポートしています。qxl.heads=N カーネルパラメータで変更することができます。

QXL デバイスのデフォルトの VGA メモリサイズは 16M です (VRAM のサイズは 64M です)。1920x1200 のモニターを2台使用しようとすると 2 × 1920 × 4 (色深度) × 1200 = 17.6 MiB の VGA メモリが必要になるためメモリが不足します。-vga qxl-vga none -device qxl-vga,vgamem_mb=32 に置き換えることでメモリ容量を変更できます。vgamem_mb を 64M 以上に増やした場合、vram_size_mb オプションも増やす必要があります。

コピーアンドペースト

ホストとゲスト間のコピーアンドペーストを行うには spice エージェント通信チャンネルを有効にする必要があります。それには virtio-serial デバイスをゲストに追加して、spice vdagent のためにポートを開かなければなりません。また、ゲストへの spice vdagent のインストールも必須です (Arch ゲストの場合は spice-vdagent、Windows ゲストの場合は Windows ゲストツール)。エージェントが動いていること (さらに、今後のために、自動で起動すること) を確認してください。QEMU で SPICE プロトコルを使う方法は #SPICE を参照してください。

Windows 特有のノート

QEMU は Windows 95 から Windows 10 まで全てのバージョンの Windows を動かすことができます。

QEMU で Windows PE を実行することも可能です。

高速スタートアップ

ノート: 電源設定を変更するには管理者権限が必要です。

Windows 8 (あるいはそれ以降) をゲストにする場合、コントロールパネルの電源オプションから"高速スタートアップ"を無効にしないと、起動時にゲストがフリーズすることがあります。

-smp オプションを正しく適用するために高速スタートアップを無効化しなくてはならないこともあります。

Remote Desktop Protocol

MS Windows ゲストを使っている場合、RDP を使ってゲスト VM に接続する方法もあります。VLAN を使用してしてゲストが同じネットワークにない場合、次を使って下さい:

$ qemu-system-x86_64 -nographic -net user,hostfwd=tcp::5555-:3389

そして Rdesktopfreerdp を使ってゲストに接続してください。例えば:

$ xfreerdp -g 2048x1152 localhost:5555 -z -x lan

Clone Linux system installed on physical equipment

Linux system installed on physical equipment can be cloned for running on QEMU vm. See Clone Linux system from hardware for QEMU virtual machine

Chrooting into arm/arm64 environment from x86_64

Sometimes it is easier to work directly on a disk image instead of the real ARM based device. This can be achieved by mounting an SD card/storage containing the root partition and chrooting into it.

Another use case for an ARM chroot is building ARM packages on an x86_64 machine - armutils-gitAUR can be used for that. Here, the chroot environment can be created from an image tarball from Arch Linux ARM - see [5] for a detailed description of this approach.

Either way, from the chroot it should be possible to run pacman and install more packages, compile large libraries etc. Since the executables are for the ARM architecture, the translation to x86 needs to be performed by QEMU.

Install qemu-user-static on the x86_64 machine/host. The package will take care of registering the qemu binaries to binfmt service. あ Restart systemd-binfmt.service

qemu-user-static is used to allow the execution of compiled programs from other architectures. This is similar to what is provided by qemu-emulators-full, but the "static" variant is required for chroot. Examples:

qemu-arm-static path_to_sdcard/usr/bin/ls
qemu-aarch64-static path_to_sdcard/usr/bin/ls

These two lines execute the ls command compiled for 32-bit ARM and 64-bit ARM respectively. Note that this will not work without chrooting, because it will look for libraries not present in the host system.

qemu-user-static allows automatically prefixing the ARM exectuable with qemu-arm-static or qemu-aarch64-static.

Make sure that the ARM executable support is active:

$ ls /proc/sys/fs/binfmt_misc
qemu-aarch64  qemu-arm	  qemu-cris  qemu-microblaze  qemu-mipsel  qemu-ppc64	    qemu-riscv64  qemu-sh4    qemu-sparc	qemu-sparc64  status
qemu-alpha    qemu-armeb  qemu-m68k  qemu-mips	      qemu-ppc	   qemu-ppc64abi32  qemu-s390x	  qemu-sh4eb  qemu-sparc32plus	register

Each executable must be listed.

If it is not active, reinstall binfmt-qemu-staticAUR[リンク切れ: package not found] and restart systemd-binfmt.service.

Mount the SD card to /mnt/sdcard (the device name may be different).

# mkdir -p /mnt/sdcard
# mount /dev/mmcblk0p2 /mnt/sdcard

Mount boot partition if needed (again, use the suitable device name):

# mount /dev/mmcblk0p1 /mnt/sdcard/boot

Finally chroot into the SD card root as described in Change root#Using chroot:

# chroot /mnt/sdcard /bin/bash

Alternatively, you can use arch-chroot from arch-install-scripts, as it will provide an easier way to get network support:

# arch-chroot /mnt/sdcard /bin/bash

You can also use systemd-nspawn to chroot into the ARM environment:

# systemd-nspawn -D /mnt/sdcard -M myARMMachine --bind-ro=/etc/resolv.conf

--bind-ro=/etc/resolv.conf is optional and gives a working network DNS inside the chroot

Not grabbing mouse input

この記事あるいはセクションで使われている用語や表現には問題が存在します。
議論: It is not explained what the option actually does. Is it causing or avoiding the side effect? (議論: トーク:QEMU#)

Tablet mode has side effect of not grabbing mouse input in QEMU window:

-usb -device usb-tablet

It works with several -vga backends one of which is virtio.

トラブルシューティング

仮想マシンの動作が遅すぎる

仮想マシンのパフォーマンスを向上させることができる多数のテクニックがあります。例えば:

  • -cpu host オプションを使うことで QEMU にホストの CPU を正確にエミュレートさせることができます。このオプションを使わない場合、もっと一般的な CPU がエミュレートされます。
  • Windows ゲストの場合、Hyper-V enlightenments を有効にしてください: -cpu host,hv_relaxed,hv_spinlocks=0x1fff,hv_vapic,hv_time
  • ホストマシンに CPU が複数ある場合は、-smp オプションを使ってゲストにもっと多くの CPU を割り当てて下さい。
  • 仮想マシンに十分なメモリを割り当てているか確認してください。デフォルトでは、QEMU はそれぞれの仮想マシンに 128 MiB のメモリしか割り当てません。-m オプションを使って多めのメモリを割り当てて下さい。例えば、-m 1024 で仮想マシンは 1024 MiB のメモリを使って動作します。
  • 可能な限り KVM を使って下さい: QEMU の起動コマンドに -machine type=pc,accel=kvm を追加します。
  • ゲストのオペレーティングシステムのドライバーによってサポートされているときは、ネットワークやブロックデバイスに virtio を使って下さい。例えば:
$ qemu-system-x86_64 -net nic,model=virtio -net tap,if=tap0,script=no -drive file=disk_image,media=disk,if=virtio
  • ユーザーモードネットワークの代わりに TAP デバイスを使って下さい。#QEMU の Tap ネットワーク を参照。
  • ゲスト OS がディスクへの書き込みを頻繁に行う場合、ホストのファイルシステムで特定のマウントオプションを使うと良いかもしれません。例えば、ext4 ファイルシステムbarrier=0 オプションでマウントすることが考えられます。ファイルシステムのパフォーマンスを向上させるオプションは、場合によってデータの保全性を犠牲にする可能性があるので、変更するオプションのドキュメントを読んでおいたほうが無難です。
  • raw ディスクイメージを使っている場合、キャッシュを無効にする:
$ qemu-system-x86_64 -drive file=disk_image,if=virtio,cache=none
  • ネイティブの Linux AIO を使用する:
$ qemu-system-x86_64 -drive file=disk_image,if=virtio,aio=native,cache.direct=on
  • qcow2 ディスクイメージを使用している場合、十分な容量の L2 キャッシュを割り当てることで I/O の性能が著しく改善することがあります。L2 キャッシュを計算するときの 公式 は: l2_cache_size = disk_size * 8 / cluster_size です。デフォルトのクラスタサイズ 64K で、容量 8 GB の qcow2 イメージを作成した場合、最適な L2 キャッシュは 1 MB となります。QEMU はデフォルトでは 1 MB しか L2 キャッシュを使用しません。QEMU のコマンドラインでキャッシュの容量を指定することができます。例えば使用するキャッシュを 4 MB にするには:
$ qemu-system-x86_64 -drive file=disk_image,format=qcow2,l2-cache-size=4M
  • 複数の仮想マシンを同時に動かしていて、全て同じオペレーティングシステムをインストールしている場合、kernel same-page merging を有効にすることでメモリを節約できます。#KSM を有効にするを見てください。
  • 場合によっては、ゲストのオペレーティングシステムでメモリバルーニングドライバーを実行して QEMU を -balloon virtio オプションで起動することで、実行中の仮想マシンからメモリを回収することができます。

詳しくは http://www.linux-kvm.org/page/Tuning_KVM を参照してください。

マウスカーソルが敏感すぎたり迷走する

カーソルが画面を飛び回って手に負えない場合、QEMU を起動する前にターミナルに次を入力することで直るかもしれません:

$ export SDL_VIDEO_X11_DGAMOUSE=0

このコマンドで直ったら、~/.bashrc ファイルにコマンドを追加することができます。

カーソルが表示されない

マウスカーソルを表示するには -show-cursor を QEMU のオプションに追加してください。

オプションを追加しても表示されない場合、ディスプレイデバイスが正しく設定されているか確認してください。例: -vga qxl

Two different mouse cursors are visible

Apply the tip #Mouse integration.

カーソルが移動・アタッチできない

QEMU オプションの -usbdevice tablet-usb に置き換えてください。

Keyboard issues when using VNC

When using VNC, you might experience keyboard problems described (in gory details) here. The solution is not to use the -k option on QEMU, and to use gvncviewer from gtk-vnc. See also this message posted on libvirt's mailing list.

キーボードが壊れているまたは矢印キーが動作しない

キーの一部が動かなかったり間違ったキーが押されてしまう (特に矢印キー) ときは、おそらくキーボードレイアウトをオプションとして指定する必要があります。キーボードレイアウトは /usr/share/qemu/keymaps で探すことができます。

$ qemu-system-x86_64 -k keymap disk_image

Could not read keymap file

qemu-system-x86_64: -display vnc=0.0.0.0:0: could not read keymap file: 'en'

is caused by an invalid keymap passed to the -k argument. For example, en is invalid, but en-us is valid - see /usr/share/qemu/keymaps/.

ウィンドウのリサイズでゲストのディスプレイが引き伸ばされる

デフォルトのウィンドウサイズに戻すには、Ctrl+Alt+u を押して下さい。

ioctl(KVM_CREATE_VM) failed: 16 Device or resource busy

-enable-kvm オプションを使って QEMU を起動した時に以下のようなエラーメッセージが表示される場合:

ioctl(KVM_CREATE_VM) failed: 16 Device or resource busy
failed to initialize KVM: Device or resource busy

他のハイパーバイザが動作しています。同時に複数のハイパーバイザを動かすのは推奨されていません、もしくは不可能です。

libgfapi エラーメッセージ

起動時に以下のエラーメッセージが表示される場合:

Failed to open module: libgfapi.so.0: cannot open shared object file: No such file or directory

任意の依存パッケージである GlusterFS が存在しないというだけなので無視して問題ありません。glusterfs パッケージをインストールすれば消えます。

ライブ環境でカーネルパニックが発生する

ライブ環境を起動した場合に以下が発生する場合:

[ end Kernel panic - not syncing: VFS: Unable to mount root fs on unknown block(0,0)

-m VALUE スイッチを付けて適当な量の RAM を指定して VM を起動してみてください。RAM が足りなくなると上記のような問題が発生することがあります。

Windows 7 ゲストの音質が酷い

Windows 7 ゲストで hda オーディオドライバーを使用すると音質に問題が発生することがあります。QEMU の引数に -soundhw ac97 を指定してオーディオドライバーを ac97 に変更し、ゲストに Realtek AC'97 Audio Codecs の ac97 ドライバーをインストールすることで問題は解決します。詳しくは Red Hat Bugzilla – Bug 1176761 を参照してください。

Could not access KVM kernel module: Permission denied

以下のエラーが表示される場合:

libvirtError: internal error: process exited while connecting to monitor: Could not access KVM kernel module: Permission denied failed to initialize KVM: Permission denied

Systemd によって kvm グループに動的 id が割り当てられていることが原因です (FS#54943 を参照)。エラーを解決するには /etc/libvirt/qemu.conf ファイルを編集して以下の行を:

group = "78"

以下のように変更してください:

group = "kvm"

Windows の仮想マシンを起動したときに "System Thread Exception Not Handled"

Windows 8 や Windows 10 ゲストが起動時に "System Thread Exception Not Handled" という例外を発生させることがあります。実機で古いドライバーの動作がおかしいことが原因です。KVM では CPU のモデルを core2duo に設定することで解決します。

特定の Windows のゲームやアプリケーションでクラッシュやブルスクリーンが発生する

ときどき、物理マシンでは問題なく動作するのに、仮想マシンでアプリケーションを実行するとクラッシュが発生することがあります。dmesg -wH を実行したときに MSR というエラーが表示される場合、クラッシュの原因はゲストがサポートされていない Model-specific registers (MSR) にアクセスしようとしたときに KVM が General protection fault (GPF) を起こすためです。ゲームの最適化などの機能が機能しない場合、KVM モジュールに ignore_msrs=1 オプションを指定して実装されていない MSR へのアクセスを無視することで問題は解決します:

/etc/modprobe.d/kvm.conf
...
options kvm ignore_msrs=1
...

上記のオプションが役に立つのは以下のような場合です:

  • GeForce Experience でサポートされたいない PCU が存在するとエラーが表示される。
  • StarCraft 2 や L.A. Noire で KMODE_EXCEPTION_NOT_HANDLED が発生して Windows 10 がブルースクリーンになる。
警告: 未知の MSR のアクセスを無視すると、VM 内の他のソフトウェアや他の VM が動作しなくなる可能性があります。

参照