ゲストのインストール (virt-install編)

先のページでは、qemu-kvm コマンドでゲストのインストーラを直接起動してその後普段用の起動用 qemu-kvm スクリプトに移行するという基本的な、泥臭い、解剖学的なやり方を紹介したわけだが、当節では、virt-install コマンドでインストールする現実的なやり方を紹介する。virt-install は裏で libvirt (Xenの記事参照) を使用しているため、インストールと同時にゲスト定義が libvirt のドメイン定義データベースに登録される。そのため、インストール後に通常起動用のシェルスクリプトを用意したり libvirt のドメイン定義プールに手で加えたりといった手間が要らない。virt-install のコマンドオプションはかなり限られていて仮想マシンのパラメータをきめ細かく制御することができないという欠点はあるが、それでも virt-manager よりは多少融通が利く。ゲスト定義の土台を作るためのツールだと割り切って使えばそれなりに便利な道具だ。virt-install は、RedHat 系では python-virtinst パッケージに含まれる。

ゲストインストールのための準備

ゲストのインストール (qemu-kvm直接編)」で述べたので、必要項目の詳細は前ページを参照していただきたい。ここではポイントをリストアップするだけに留める。

MACアドレス生成スクリプト (qemumacgen.py)
「qemu-kvm直接編」の時と同様に、これ(qemumacgen.py) を PATH の通った場所、例えば /usr/local/bin/ にコピーして、実行ビットを立てておく。これがなくても virt-install はランダムな MAC アドレスを生成してゲストに与えてくれるが、後述のインストールスクリプトでこれを使っていることと、/var/tmp/ に記録の残るこちらほうが少し便利だからだ。
TAPつなぎ込みスクリプト (qemu-ifup/qemu-ifdown) は不要
virt-install の場合は /etc/qemu-ifupqemu-ifdown も要らない。virt-installlibvirt 経由で qemu-kvm を起動する。libvirt はその際、自前で TAP デバイスを生成し、qemu-kvm に対してはファイルディスクリプタ指定で「このTAPを使え」と指示しているからだ。
sudoers の設定
当節で紹介するインストール用スクリプトに関しては、sudo を使用せず直接 root 権限で実行することにしているので、「qemu-kvm直接編」で述べた sudoers の設定は不要。後々 virsh でゲストを上げたり下げたりする際の利便性を考えれば、設定しておいたほうが便利ではある。
ディスクイメージの作成
qemu-kvm を直接起動する場合と何ら変わりはない。前章で述べたいずれかの形式で用意しておく。ゲストのインストール時に virt-install にサイズを指定して自動でディスクイメージを作らせることもできるようだが、筆者はやったことがない。

virt-install

以下が virt-install の主なオプション。引数のあるロングオプションは、基本的には --param=value の形式を採る。ここではショート形式は記載しない。--import--os-variant など一部を除いては、libvirt を通じての qemu への指示、言い換えると libvirt へどういった定義でゲストを登録するかを指示するものということになる。下表では、参考のために、各 virt-install オプションが qemu(-kvm) のどのオプションに呼応しているかを添えている。「オプション」欄か「呼応するqemuオプション」が空欄のものは、どちらかにそれが欠如していることを示す。オプションが qemu(-kvm) に対してどういう意味を持つかは、前章「qemu-kvm直接編」に載せた qemu-kvm のオプション表を見てもらうといいだろう。

オプション 説明 呼応する qemuオプション
--import 既存のゲストリソース (ディスクやブリッジ) をそのまま利用する。これを指定すると、インストール行程は「終わったことにして」、libvirt への定義登録とゲストの起動だけを行なう。  
--force virt-install は通常、指定されたリソースが既に他のゲストのものとして libvirt に登録されていた場合、処理を断る。インポートの時など、同じリソースで別のゲスト定義を作りたい場合にこのオプションが必要。  
--noreboot ゲストのインストールが終了した後、ゲストを再起動しない。--import と一緒に使うとゲストは一度も起動せずに libvirt への定義登録だけが行われる結果となり、libvirt 上に定義の土台を作るのに便利。その後 `virsh edit' で調整してから手動で起動すればいい。  
--name=name ゲストの定義名。 -name
--vcpus=N 仮想プラットフォームを、N 個の CPU を持つ SMP システムとしてエミュレートする。 -smp
--ram=X ゲストに与えるメモリ量。単位はMB。 -m
--cdrom=file ゲストの CD デバイスに割り当てるホスト上のデバイスファイルかイメージファイル。下記の --disk 様式でも指定できるが、こちらの書き方は「仮想CDROMがインストールメディアである」の意味を含む。 -cdrom
--location=URI インストールソースの指定。インストール媒体のイメージファイルのあるディレクトリへのPATH、nfs:host:/pathhttp://host/pathftp://host/path といった具合に様々な方法が指定できる。  
--disk options ディスクデバイスの指定。例:
--disk path=/var/lib/kvm/images/centos5u.img,bus=virtio
path=file ドライブとしてゲストに提供するデバイスファイルやディスクイメージファイルなど。 file
bus=iface このドライブの接続インターフェイス。ide, scsi, usb, virtio, xen の5つがある。 if
  ドライブ番号を指定する qemuindex に相当するものはない。 index=N
  bus=scsi などの場合にバス序数とユニットID を指定する qemu の右記オプションに相当するものはない。 bus=X,unit=Y
device=type ディスクのメディアタイプ。diskcdrom または floppy。デフォルトは disk media
cache=mode ハイパーバイザ(つまりホストOS側)でのディスクキャッシュ制御。writeback はR/Wとも有効、writethrough はRのみ、none はR/Wとも無効。none が一番速いはずだが、検証の結果、none だとゲストインストールに失敗する。デフォルトの writeback (つまり記述しない) が最も安定か。 cache
  qemu の右記オプションに相当するオプションはなく自動判定。 boot=on
-drive
  ブートデバイスの指定専用の文言はない。--cdrom--location で指定したものがブートデバイスとされる。 -boot
--network=type:name ゲストをホストのどのネットワークにつなぐか。type 部は bridge, network, user のいずれか。詳しくは例を参照。エミュレートするNICのモデルを指定する方法はない(RHEL/CentOS 5.5の時点)。 -net
--mac=mac MACアドレスはこのように独立したオプション (RHEL/CentOS 5.5の時点)。上記とセットで書く。詳しくは例を参照。 -net
--sound ゲストにサウンドカードを与えるかどうか。モデル名は指定できない。 -soundhw
  UHCI USB デバイスに関するオプションはない。 -usb
  ゲストのシリアルポートに関するオプションはない。libvirt へは `-serial pty' に相当するパラメータで登録される。 -serial
  ゲストのパラレルポートに関するオプションはない。libvirt へは `-parallel none' に相当するパラメータで登録される。 -parallel
--vnc ゲストのVGA 出力を VNC で表示する。VNCポートの指定は下記の別オプションで書く。 -vnc
--vncport=port VNCのポート番号。qemu に指定するような 5900 からの相対でなく、5901 などポート番号そのものを書く。 -vnc
--keymap=code ゲストに対してエミュレートするキーボードのレイアウト。ホストに日本語キーボードをつないでいるのなら ja を指定。 -k
  ゲストの仮想BIOSクロックをホストのローカルタイムで与えたくても指定方法がない。libvirt へは常に UTC として登録されてしまう。 -localtime
--os-type=type ゲストOSのタイプを指定すると、それに応じて virt-install が最適な QEMU パラメータを加える。タイプは linux, windows, solaris, unix など。下記の --os-variant を指定する場合には不要。  
--os-variant=type 上記 --os-type をもっと細分化したもの。実際の挙動を見ていると、インストール後に必要な再起動の回数などもこれによって予測している気がする。python-virtinst-0.400.3-5.el5 (2010/1/31 観察) で指定可能なものは fedora5 から 11, rhel2.1, rhel3 から 5, vista, win2k, win2k3, win2k8, winxp, winxp64, sles10, ubuntujaunty, debianetch, freebsd6 など。その他に、generic24 (kernel 2.4.x 一般) や generic26 (kernel 2.6.x 一般)、virtio26 (virtioを備えた2.6.25以降のカーネル一般) といった汎用型もあったりする。詳しくは man を。
ただし、ACPI や APIC が充分普及する前の OS をインストールする場合、当オプションを指定すると '--noacpi --noapic' (ACPI, APIC とも無効) が勝手に付加されることがあり、シャットダウンで電源が切れない OS になってしまう。例えば Windows2000 ゲストの場合には --os-variant--os-type を指定しないほうがよい。
 
--accelerate ゲストのインストール時に、可能ならば KVM あるいは KQEMU の備えるカーネルアクセラレーションを活用する。インストール後の libvirt定義やゲストの挙動には影響はないが、これを付けないと明らかにインストールが遅い。KVM のアクセラレーション機能と KQEMU がどちらも使用可能な環境では、前者が優先使用される。  
--noautoconsole virt-install はゲストプロセスが開始し次第 Virt Viewer を起動してゲストのコンソールを表示しようとするが、それを抑止したい時に使う。  
--noreboot インストール完了後に自動的にゲストをリブートしない。  

ゲストインストールの実例

ここでは、以下の条件をベースにゲストOS を virt-install コマンドでインストールすることにする。なるべく前ページ「ゲストのインストール(qemu-kvm直接編)」と対応させるように構成したつもりなので、見比べてもらうと面白いかもしれない。

インストール用 virt-install 起動スクリプト

筆者は、virt-install のコマンドをいちいち全部打つのが面倒臭いので、簡素なスクリプトテンプレート qemu-virt-install を作ってインストールのキックに使っている。下記のようなものだ。スクリプトの引数はゲストの名称。これを、どこでも構わないのだが、例として /usr/local/bin/ に置いておくことにしよう (root:root 755)。実際には、いろいろなパターンに合わせてこのスクリプトを複製・編集することになるだろう。その際、序盤の決まり切ったルーティンやファンクション定義が各々のファイルにあるのはカッコ悪いので、その部分を別体インクルードファイルにした。それ qemu-install-common.sh (qemu-kvm直接起動の時と同じもの) も同一ディレクトリにひとつだけ置いておいていただきたい。

サンプルパターン 1

仮想ハードディスクは、メイン用及びスワップ用にそれぞれイメージファイルを IDEディスクとして提供。virtio を使わないパターン。

#!/bin/bash
 
dir=$(dirname $0)
[ -f ${dir}/qemu-install-common.sh ] || exit 1
. ${dir}/qemu-install-common.sh
 
mac_gen $1 0
mac_gen $1 1
 
exec virt-install \
--cdrom=/dev/cdrom \
--name=$1 \
--ram=768 \
--vcpus=2 \
--disk path=/var/lib/kvm/images/$1.img \
--disk /var/lib/kvm/images/${1}-swap.img \
--os-variant=rhel5 \
--accelerate \
--network=bridge:br0 --mac=$newmac0 \
--network=network:virnet0 --mac=$newmac1 \
--vnc \
--vncport=5900 \
--keymap=ja
サンプルパターン 2

仮想ハードディスクは、メイン用及びスワップ用にそれぞれ LVMLVvirtio ディスクとして提供。

RedHat 系のゲストでは、RHEL 4.8 以降と 5.3 以降なら virtio ドライバを標準で備えているので、このようなやり方でインストール時からいきなり virtio 化できる。RHEL 4.7 以前や RHEL 3.x では、インストール後に kmod-virtio というパッケージを追加する必要があるため、いきなりの virtio 化は難しそうだ。Windowsゲストの場合も、インストール時には virtio は使わないほうがいい (このことについては後でもう少し詳しく述べる)。

ネットワークインターフェイスは、virt-install ではモデルを指定する術がなく、インストール時には virtio 化できない。仕方ないのでインストール後に調整する。

#!/bin/bash
 
dir=$(dirname $0)
[ -f ${dir}/qemu-install-common.sh ] || exit 1
. ${dir}/qemu-install-common.sh
 
mac_gen $1 0
mac_gen $1 1
 
exec virt-install \
--cdrom=/var/tmp/CentOS-5.4-x86_64-bin-DVD.iso \
--name=$1 \
--ram=768 \
--vcpus=2 \
--disk path=/dev/mapper/VolGroup00-LogVol00,bus=virtio \
--disk path=/dev/mapper/VolGroup00-LogVol01,bus=virtio \
--os-variant=rhel5 \
--accelerate \
--network=bridge:br0 --mac=$newmac0 \
--network=network:virnet0 --mac=$newmac1 \
--vnc \
--vncport=5900 \
--keymap=ja

インストールの開始

では、インストールを開始しよう。スクリプトでインストールソースに実デバイスを指定した場合はホストのドライブにインストールDVD を挿入しておく。そうしたら、上記のスクリプトをコールする。このスクリプトは root で実行しなければならない。引数はゲストの定義名だ。

root# /usr/local/bin/qemu-virt-install rhel5u

エラーがなければ、Virt Viewer (libvirt 付属のVNCコンソール) が開いてゲストのインストール画面が表示されるはずだ。幾つか注意点を挙げると、

libvirt上でのゲスト定義の調整

インストールしたゲストの定義を、virsh コマンドを使って修正・補完する。

root# virsh edit rhel5u

とコマンドすると、テンポラリな XML ファイルにダンプされた定義情報が vi によって開かれるので、下記のサンプルの要領で修正する (rhel5u_kvm.xml)。なお、一旦 XML ファイルとしてきちんと手元に置いてから再取り込みする方法もあるが、そのあたりの詳しい話は、以前書いた Xen の記事の「libvirt の XML 形式」や「コマンドラインツール」の項を参照していただくとしよう。libvirt XML の記述法は libvirt のオフィシャルページ で調べられる。vi の使い方に困った人はこちら

<domain type='kvm'>
  <name>rhel5u</name>
  <uuid>63813ee3-9708-313c-7cd6-3eb3cca9621e</uuid>
  <memory>786432</memory>
  <currentMemory>786432</currentMemory>
  <vcpu>2</vcpu>
  <os>
    <type arch='x86_64' machine='pc'>hvm</type>
    <boot dev='hd'/>
  </os>
  <features>
    <acpi/>
    <apic/>
    <pae/>
  </features>
  <clock offset='localtime'/>         <-- virt-install では必ず utc になってしまうので修正
  <on_poweroff>destroy</on_poweroff>
  <on_reboot>restart</on_reboot>
  <on_crash>restart</on_crash>
  <devices>
    <emulator>/usr/libexec/qemu-kvm</emulator>
    <disk type='block' device='cdrom'>
                                      <-- 実リソースなしCDROMは、'<source/>'ブロックを書かないことによって作れる
      <target dev='hdc' bus='ide'/>
      <readonly/>
    </disk>
    <disk type='block' device='disk'>
      <source dev='/dev/mapper/VolGroup00-LogVol00'/>
      <target dev='vda' bus='virtio'/>
    </disk>
    <disk type='block' device='disk'>
      <source dev='/dev/mapper/VolGroup00-LogVol01'/>
      <target dev='vdb' bus='virtio'/>
    </disk>
    <interface type='bridge'>
      <mac address='54:52:00:64:a6:35'/>
      <source bridge='br0'/>
      <target dev='vnet0'/>        <-- libvirt ではTAPはファイルディスクリプタを使って指定され、/etc/qemu-ifup は使われない
      <model type='virtio'/>       <-- NIC をvirtio で提供するなら付け加える
    </interface>
    <interface type='network'>
      <mac address='54:52:00:64:ef:32'/>
      <source network='virnet0'/>
      <target dev='vnet1'/>
      <model type='virtio'/>
    </interface>
    <sound model='ac97'/>          <-- サウンドデバイスを与えるなら挿入
    <serial type='pty'>
      <source path='/dev/pts/2'/>
      <target port='0'/>
    </serial>
    <console type='pty' tty='/dev/pts/2'>
      <source path='/dev/pts/2'/>
      <target port='0'/>
    </console>
    <input type='mouse' bus='ps2'/>
    <graphics type='vnc' port='5901' autoport='no' keymap='ja'/>  <-- 常用用に port を適当なものに変えるとよい
  </devices>
</domain>

インストール時にディスクを virtio にしなかったのにこの段階で欲張って virtio ディスクに変更するのは、やめておいたほうがいい。ネットワークの方は、RHEL/CentOS の 5.3 以降及び RHEL 4.8 以降や Fedora Core 9 以降なら標準でドライバを持っているので virtio 化して構わない。ただし、RHEL 5.4 ホスト上の virt-install での検証によると、--os-variant で指定したゲストディストリビューションが例えば Fedora9 だった場合、virt-install はゲストが virtio ドライバを持っていると判断したようで、NIC は最初から virtio で提供されていた。ドライバディスクの必要な Windows ゲストを後から virtio 化したり、Linux ゲストのブートディスクを後から virtio 化する手順については、この後に触れる。

その他の留意点:

インストール後のゲストを virtio 化する

Linuxゲストのブートディスクを virtio 化する

以下の順序で変更を行なう。

1. ゲストの modprobe.conf の修正

/etc/modprobe.conf がデフォルトで存在する「非先鋭的」なディストリビューションでは、そこに記述を加えたほうがいいかもしれない。ただし、CentOS 5.4 でテストしたところ、書かなくても virtio 化は成功し、切り替えた後に自動的に書き加えられることもなかった。加えておくなら、

alias scsi_hostadapter ata_piix     <- おそらくこの記述があるので、
alias scsi_hostadapter1 virtio_blk  <- この行を加える

2. ゲストの initrd イメージの作り直し

現在の初期RAMイメージを念のためバックアップしてから、virtio_blk ドライバ入りのイメージを作り直してやる。

root# cd /boot
root# cp -p initrd-$(uname -r).img initrd-$(uname -r)_ide.img
root# mkinitrd --with=virtio_pci --with=virtio_blk -v -f \
 initrd-$(uname -r).img  $(uname -r)

肝心なのは --with オプション。最初、virtio_blk だけ指定して玉砕していた。このように、バスの幹となる virtio_pci モジュールも入れてやらないとだめだ。これが完了したら、ゲストをシャットダウンする。

3. ゲスト定義の修正

virsh で定義を開き修正を開始する;

root# virsh edit GuestName

修正するのは下記の部分;

<domain type='kvm'>
<-------------- 中略 ---------------->
    <disk type='block' device='cdrom'>
      <target dev='hdc' bus='ide'/>      <-- CDROMまでvirtioにする意味はないだろう。変えない
      <readonly/>
    </disk>
    <disk type='block' device='disk'>
      <source dev='/dev/mapper/VolGroup00-LogVol00'/>
      <target dev='vda' bus='virtio'/>   <-- dev の `hda' を `vda' に。bus の `ide' を `virtio' に変える
    </disk>
    <disk type='block' device='disk'>
      <source dev='/dev/mapper/VolGroup00-LogVol01'/>
      <target dev='vdb' bus='virtio'/>   <-- 複数の仮想ハードディスクがあるならそちらも変えておく
    </disk>
<-------------- 中略 ---------------->
</domain>

4. ゲストの起動

virsh コマンドもしくは Virt-Manager から起動すれば、ゲストの HDD はもう virtio に切り替わっているはずだ。ゲスト上で lspci や `modprobe -c |grep virtio' したり、ホスト上で `virsh dumpxml GuestName' や `ps axww |grep qemu-kvm' で確認してみるべし。

Linuxゲストのネットワークインターフェイスを virtio 化する

ディスクと違い、先にゲスト側で何かしておく必要ない。`virsh edit ...' で <interface> ブロック内に <model type='virtio'/> を挿入するだけだ (具体的なサンプルは前述「ゲストインストールの実例」の中の XML 記述例を参照)。

ただし、変更直後のゲストOS では kudzu が働いてそれまでの NIC は無効にされ、起動したばかりの状態では virtio NIC は機能しないだろう。kudzu が変更を加えた場合、/etc/modprobe.conf~ が存在すると思われるので、本物の modprobe.conf をリネームして modprobe.conf~ と入れ替えた上で、そこに下記の記述 (ここまでの構築例に使ってきた仮想NIC 2枚差しの場合) を加える (または修正する)。

alias eth0 virtio_net
alias eth1 virtio_net 

また、kudzu の仕業により /etc/sysconfig/network-scripts/ifcfg-eth0.bakifcfg-eth1.bak が存在すれば、それらも .bak なしにリネームして復活させる。あとは `service network restart' で virtio の NIC が活性化するはずだ。

Windowsゲストを virtio 化する

まずは兎も角、Windows ゲストにインストールするための virtio ドライバを入手しなくてはならない。入手先等は、「ホストOSの準備」に書いた「パッケージ」のところを参照していただきたい。

RHEL 5.4 の virtio-win パッケージだと、ブロックドライバとネットワークドライバの msi 形式インストーラーの収められた ISO イメージの他に、ブロックドライバとネットワークドライバ + Windows Server 2003 用 txtsetup.oem ファイルの入ったフロッピーイメージも収録されている。それらイメージファイルはホストの /usr/share/virtio-win/ にインストールされる。いずれも、対応ゲストOS は Win2k3 と Win2k8 だけのように見えるが、"RHEL 5.4 Virtualization Guide" によると Vista にも対応していると書かれている。XP はネットワークドライバだけが対応との謳いなので、XP ゲストのハードディスクを virtio にしたい場合は下記のフリー版のほうを使おう。なお、RHEL 5.4 の virtio-win パッケージのドライバフロッピーイメージに入っている txtsetup.oem は下のようなものだった;

[Disks]
d1 = "OEM DISK (SCSI) Win2003/32-bit",\disk1,\i386\Win2003
d2 = "OEM DISK (SCSI) Win2003/64-bit",\disk1,\amd64\Win2003
 
[Defaults]
SCSI = WNET32
 
[scsi]
WNET32 = "Red Hat VirtIO SCSI Disk Device Win2003/32-bit"
WNET64 = "Red Hat VirtIO SCSI Disk Device Win2003/64-bit"
 
[Files.scsi.WNET32]
driver = d1, viostor.sys, viostor
inf    = d1, viostor.inf
catalog= d1, viostor.cat
 
[Files.scsi.WNET64]
driver = d2, viostor.sys, viostor
inf    = d2, viostor.inf
catalog= d2, viostor.cat
 
[HardwareIds.scsi.WNET32]
id = "PCI\VEN_1AF4&DEV_1001&SUBSYS_00000000", "viostor"
id = "PCI\VEN_1AF4&DEV_1001&SUBSYS_00020000", "viostor"
id = "PCI\VEN_1AF4&DEV_1001&SUBSYS_00021AF4", "viostor"
 
[HardwareIds.scsi.WNET64]
id = "PCI\VEN_1AF4&DEV_1001&SUBSYS_00000000", "viostor"
id = "PCI\VEN_1AF4&DEV_1001&SUBSYS_00020000", "viostor"
id = "PCI\VEN_1AF4&DEV_1001&SUBSYS_00021AF4", "viostor"
 
[Config.WNET32]
value = Parameters\PnpInterface,5,REG_DWORD,1
 
[Config.WNET64]
value = Parameters\PnpInterface,5,REG_DWORD,1

かたや、フリー版ならば、KVM のサイトから入手する。2010/1/31 現在、ブロックドライバは Vista/7/2003/2008 の x86 及び amd64 と、XP の x86。ネットワークドライバは Vista/7/XP/2003/2008 の x86 及び amd64 と、Windows 2000 用が含まれている。これらと同じドライバを ISO イメージにまとめたものを、"/contrib/famzah" というサイトが提供してくれている。ただし、いずれのドライバも署名はされていないので、そのままでは 64bit 版 Windows にはインストーできないのではないだろうか。

以下の検証は Windows Server 2003 R2 (x86) と 2008 (amd64)、XP SP2 で行なった。

Windowsゲストのシステムドライブを virtio 化する

Windows ゲストのシステムドライブを virtio 化するには、システムドライブでないドライブを先に virtio 化しておいてからシステムドライブを virtio 化する。

Windows インストールメディアからのブート時にドライバを読み込ませるやり方 (2003 の F6 キーや 2008 のドライバ読み込み) に何度も挑戦したみたが、2003 や XP ではテキストセットアップの後の再起動のあとブートせず。2008 ではドライバの追加読み込み後に、ディスクは見えるがパーティションが作成できないという状態だったりして断念した。ただ、Windows ゲストのインストール時にフロッピードライブを与えるということ自体はテクニックとして有用な場面も出てくると思うので、その際の virt-install オプションを書き留めておく。fdc という bus タイプは virt-install の man には載っていないが、こうしないと、HDD と FDD のデバイスがかぶるかのようなエラーを吐いて QEMU が起動しなかった記憶がある;

exec virt-install \
 --cdrom=/dev/cdrom \
 --name=$1 \
 --ram=768 \
 --vcpus=2 \
 --disk path=/dev/mapper/VolGroup00-LogVol00,bus=virtio \
 --disk path=/usr/share/virtio-win/virtio-drivers.vfd,device=floppy,bus=fdc \
<----- 後略 ----->

では本題に入ろう。手順をまとめると以下のようになる。virtio ドライバは、実践的には ISOイメージ版のほうが使いやすいと感じている。

  1. [ホストが RHEL 5.4 の場合のみ] Virt-Manager (仮想マシンマネージャ) を使うなりして Windows ゲストに /usr/share/virtio-win/virtio-win.iso をソースとする CDROM ドライブを与える。そして、ゲスト上で、CDROM ドライブ内の msi をダブルクリックしてドライバをインストールする。
  2. Windows ゲストをシャットダウンする。
  3. "システムドライブ以外のドライブ" がない場合は、一時的に与える小容量 (例えば 512MB) のダミーのディスクを用意する。LVM でもイメージファイルでも構わない。
  4. `virsh edit ...' でゲストの定義を修正する。ポイントは下記;
    <disk type='block' device='cdrom'>
      <source file='/PATH/TO/VIOSTOR.iso'/> <-- CDROMのソースをvirtioドライバISOファイルにする
      <target dev='hdc' bus='ide'/>          <-- 変えないで ide のまま
      <readonly/>
    </disk>
    <disk type='block' device='floppy'>      <-- ドライバを仮想フロッピーで与えたければこんな具合
      <source file='/PATH/TO/VIOSTOR.vfd'/>
      <target dev='fda' bus='fdc'/>
    </disk>
    <disk type='block' device='disk'>
      <source dev='/dev/mapper/VolGroup00-LogVol00'/>
      <target dev='hda' bus='ide'/>      <-- この段階ではシステムディスクには変更を加えない
    </disk>
    <disk type='block' device='disk'>
      <source dev='/dev/mapper/VolGroup00-LogVol01'/>
      <target dev='vda' bus='virtio'/>   <-- 非システムディスクまたはダミーのディスク。dev は 'vda' に
    </disk>
  1. Windows ゲストを起動する。暫くするとゲスト上で SCSI コントローラとしての virtio バスと副ハードディスクが検出される。ドライバを求められたら、フリー版なら仮想CDROMから取り込ませる。RHEL 5.4 ホスト上の場合でもし求められたら、ゲストの C:\Program Files (x86)\Redhat\ 下にドライバ一式がある。ドライバがインストールできたら一旦 Windows ゲストをシャットダウンする。
  2. 再度 virsh で定義を修正する;
    <disk type='block' device='cdrom'>
      <source file='/PATH/TO/VIOSTOR.iso'/> <-- CDROMのソースは念のためvirtioドライバISOファイルを指したまま
      <target dev='hdc' bus='ide'/>          <-- 変えないで ide のまま
      <readonly/>
    </disk>
    <disk type='block' device='disk'>
      <source dev='/dev/mapper/VolGroup00-LogVol00'/>
      <target dev='vda' bus='virtio'/>    <-- システムディスクもvirtioにする。バスの第1ディスクなので dev を 'vda' に
    </disk>
    <disk type='block' device='disk'>
      <source dev='/dev/mapper/VolGroup00-LogVol01'/>
      <target dev='vdb' bus='virtio'/>    <-- dev を 'vdb' にずらす
    </disk>
  1. Windows ゲストを起動する。暫くするとゲスト上でまた SCSI コントローラと virtio ディスクが検出される。ドライバを求められたら仮想CDROMから取り込ませる。
  2. ダミーディスクを使った場合は、ゲストをもう一度シャットダウンし、定義からダミーディスクを削除する。

ゲストドメインの自動起動 (virtdomains)

libvirt には、libvirtd の起動と同時にゲストドメインを起動させる仕組みがある。

root# virsh autostart GuestName

このコマンドが、やっと最近の libvirt で機能するようになった。また、同じことは、Virt-Manager GUI で当該ゲストの Boot Options の項の中にある Start virtual machine on host boot up にチェックを付けることでも設定できる。これらの設定によって、ゲスト定義ファイル(※) /etc/libvirt/qemu/rhel5u.xml へのシンボリックリンクが /etc/libvirt/qemu/autostart/ 下に作られる。機構的には virbrX を自動起動にするのとほぼ同じだ。逆に、GUI で同アイテムのチェックマークを外すとシンボリックリンクが削除される。解除のほうを virsh コマンドでやるなら `virsh autostart --disable GuestName ' となる。

※ libvirt のゲスト定義ファイル: 正確に言うと、KVM による仮想化の場合、libvirt はファイル実体としてのゲスト定義ファイルは必要としない。ゲストを libvirt に登録するとできる /etc/libvirt/qemu/ 下の XML ファイルは、Xen による仮想化の場合との違和感を薄める意味合いや、まさにこうした自動起動の仕組みのためにあるのではなかろうか。

ところが、今のところ、libvirt のゲストドメイン オートスタート機能は、起動の面倒はみてくれるものの、ホストがシャットダウンする際のゲストのシャットダウンはしてくれない。RHEL 5.4 や Fedora Core 10 で検証したが、ゲストは明らかに惨殺されている。そこで、自らこういうものを作らなければならなくなったわけだ。

仕組みの中心となるファイルはふたつ;

virtdomains
chkconfig 対応の SysV Initスクリプト。/etc/init.d/ に置く。
virtdomains設定ファイル
/etc/sysconfig/virtdomains。上記スクリプトの設定ファイル。

ピンときた方もおられようが、そう、virtdomains Initスクリプトは、Xen 環境用のパッケージ xendomains のパーツである xendomains 起動スクリプトを土台に作ったものだ。virtdomains設定ファイルのほうなど、まさに /etc/sysconfig/xendomains ほぼそのままで、値をちょっと変えただけのもの。ただし、Initスクリプトのほうは極度に改造してあり、内部操作はほぼ libvirt 経由オンリーに書き換えてある。

設置

Initスクリプトのほうを /etc/init.d/ に置いて root:root 755 のパーミションにしたら `chkconfig --add virtdomains' でスタートアップに登録。起動/停止順位設計は、xendomains と同じ 99/00 にしてある。もう一方の、virtdomains設定ファイルは /etc/sysconfig/virtdomains というファイル名にして置く (root:root 644)。

もうひとつ必ずやらなければならないのが、libvirt 作りつけの autostart ディレクトリの代わりをする /etc/libvirt/qemu/sysauto ディレクトリの作成だ。sysauto ディレクトリのパーミションは autostart と同じでいいだろう。パスが気に入らなければ設定ファイルで変更することもできる。

グローバル設定

設定ファイル /etc/sysconfig/virtdomains を必要に応じて編集する。xendomains の時のまま放置してある変数名や値もかなりあるので、項目毎に説明しておかなければならない。説明の都合上、記載順と説明順は前後する。

XENDOMAINS_AUTO=/etc/libvirt/qemu/sysauto

自動起動/自動終了させたいゲストの指定ファイルを置く場所。何をどう置くかは後ほど。

XENDOMAINS_RESTORE=true

後述の $XENDOMAINS_SAVE が空でなくそのディレクトリ直下にステートファイルが存在した場合、自動起動よりも先に、それらのゲストのリストアを試みる。virtdomains では、$XENDOMAINS_AUTO に指定ファイルのあるゲストしかリストア対象にならない。ただし実際のところ、筆者の実験では SAVE されたゲストが健康に復活したためしがない。

XENDOMAINS_CREATE_USLEEP=5000000

複数のゲストを自動起動する場合に、ゲスト毎に置くインターバル。単位はマイクロ秒。

XENDOMAINS_SYSRQ=""

virtdomains では使用していない。

XENDOMAINS_USLEEP=100000

virtdomains では使用していない。

XENDOMAINS_AUTO_ONLY=false

true にした場合、ホストシステム終了時の SAVE, MIGRATE は自動起動設定の実施してあるゲストにのみ作用する。ただし、true になっていても、自動起動対象以外のゲストに対してもシャットダウンの努力はする。

XENDOMAINS_SAVE=""

ホストシステム終了時に、ゲストをシャットダウンでなく SAVE したい場合には、ステートファイル保存先とするディレクトリを書いておく。例えば "/var/lib/libvirt/save"。指定されたディレクトリが存在しない時は作られる。SAVE でなくシャットダウンしてほしければサンプルのまま空に。実際のところ、筆者の実験では SAVE されたゲストが健康に復活したためしがないので、空のままにすることをお勧めする。

XENDOMAINS_MIGRATE=""

ホストシステム終了時に、ゲストをシャットダウンする代わりにマイグレーションさせたい場合には、`virsh migrate GuestName ' に続ける virsh コマンドオプションを書いておく。が、これに関しては全くテストしてないので機能するかどうかは不明。

XENDOMAINS_SHUTDOWN="--halt --wait"

virtdomains では、自動シャットダウンが機能するには必ず "--halt --wait" が入っていなければならない。実際のところは、スペース以外のどんな文字列でもいいのだが。

XENDOMAINS_SHUTDOWN_ALL="--all --halt --wait"

これにスペース以外の文字列が何か入っていれば、自動起動・終了指定した以外のゲストも、一連の処理の後シャットダウンさせようとする。空にしておくと、システム標準の killall が各 qemu-kvm プロセスに TERM シグナルを送るだろうが、それはゲストにとって即ち惨殺だ。サンプルのままにしておいてほしい。

XENDOMAINS_STOP_MAXWAIT=150

各ゲストドメインのシャットダウン完了のタイムアウト (秒)。これを過ぎると、もう一度シャットダウンを試み、だめなら destroy、最後は kill でターミネートする。MIGRATESAVE の対象となっていた場合も、それらが失敗した場合にはこの処理を受ける。

ゲストの自動起動登録

$XENDOMAINS_AUTO (既定なら /etc/libvirt/qemu/sysauto/) 直下に、自動起動/終了させたいゲストの libvirt上での定義名を書いたテキストファイルを置く。ファイル名はスペースを含まなければ何でもいいが、そもそもこのような仕組みにしたのはゲストの起動順を制御したかったからなので、頭2ケタを数字にするのがいいだろう。例えば、libvirt 定義名 rhel5u を先に、centos5u をその後で起動したければ、

root# echo rhel5u >/etc/libvirt/qemu/sysauto/00rhel5u
root# echo centos5u >/etc/libvirt/qemu/sysauto/01centos5u

とやっておけば準備完了だ。ただし、今のところシャットダウンの順序はこれに従わない。