OSS 仮想化機構KVMについての調査(基本動作手順書)

2009 情財第 554 号
オープンソフトウェア利用促進事業
OSS 仮想化機構 KVM についての調査
基本動作手順書
平成22年5月
独立行政法人 情報処理推進機構
目次
1. はじめに...............................................................................................................................................................1
2. 評価環境.............................................................................................................................................................2
2.1. システム構成..............................................................................................................................................2
2.2. ネットワーク構成........................................................................................................................................2
2.3. ストレージ構成...........................................................................................................................................3
2.4. 物理マシン構成.........................................................................................................................................3
2.5. ベースシステム..........................................................................................................................................4
2.6. システム構築..............................................................................................................................................4
2.6.1. インストール........................................................................................................................................5
2.6.2. BIOS 設定............................................................................................................................................5
2.6.3. ネットワーク環境設定.......................................................................................................................5
2.6.4. その他環境設定................................................................................................................................6
3. 使用準備.............................................................................................................................................................7
3.1. 使用ツール..................................................................................................................................................7
3.2. libvirt 使用準備..........................................................................................................................................7
3.2.1. サービスの起動設定........................................................................................................................7
3.2.2. 設定ファイル......................................................................................................................................7
3.2.3. ネットワーク設定................................................................................................................................7
3.2.4. リモート接続準備..............................................................................................................................7
3.3. スクリプト使用準備...................................................................................................................................8
4. VM の起動...........................................................................................................................................................9
4.1. VM の定義...................................................................................................................................................9
4.2. VM イメージの作成...................................................................................................................................9
4.3. VM の起動.................................................................................................................................................10
4.3.1. 実行形式...........................................................................................................................................10
4.3.2. ドメイン定義 XML............................................................................................................................10
4.3.3. インストール時の起動方法...........................................................................................................11
5. VM のライフサイクル制御..............................................................................................................................12
5.1. VM の停止.................................................................................................................................................12
5.1.1. 実行形式...........................................................................................................................................12
5.1.2. 処理補足...........................................................................................................................................12
5.2. VM の強制停止........................................................................................................................................13
5.2.1. 実行形式...........................................................................................................................................13
5.2.2. 処理補足...........................................................................................................................................13
5.3. VM の再起動............................................................................................................................................13
5.3.1. 処理補足...........................................................................................................................................13
5.4. VM の一時停止、再開............................................................................................................................13
5.4.1. 実行形式...........................................................................................................................................13
5.4.2. 処理補足...........................................................................................................................................14
5.5. VM の保存、復元.....................................................................................................................................14
5.5.1. 実行形式...........................................................................................................................................14
5.5.2. 処理補足...........................................................................................................................................14
5.6. VM の移動.................................................................................................................................................15
5.6.1. 実行形式...........................................................................................................................................15
5.6.2. 処理補足...........................................................................................................................................15
5.7. VM の情報取得(1)...................................................................................................................................15
5.7.1. 実行形式...........................................................................................................................................15
5.7.2. 処理補足...........................................................................................................................................16
5.8. VM の情報取得(2)...................................................................................................................................17
5.8.1. 実行形式...........................................................................................................................................17
5.8.2. 処理補足...........................................................................................................................................18
6. デバイスの制御................................................................................................................................................19
6.1. ディスクの定義........................................................................................................................................19
6.1.1. デバイスのタイプ.............................................................................................................................19
6.1.2. ソースファイルのタイプ..................................................................................................................19
6.1.3. インタフェースタイプ......................................................................................................................19
6.2. ディスクの動的追加・削除....................................................................................................................20
6.2.1. 実行形式...........................................................................................................................................20
6.2.2. 処理補足...........................................................................................................................................20
6.3. ネットワークインタフェースの定義.......................................................................................................20
6.3.1. ネットワークタイプ...........................................................................................................................21
6.3.2. MAC アドレス....................................................................................................................................21
6.3.3. NIC モデル........................................................................................................................................21
6.4. ネットワークインタフェースの動的追加・削除..................................................................................21
6.5. コンソールの定義....................................................................................................................................21
6.6. Windows ゲストの PV ドライバ................................................................................................................22
7. 動的なリソース変更........................................................................................................................................23
7.1. メモリ..........................................................................................................................................................23
7.2. CPU.............................................................................................................................................................23
8. 添付資料...........................................................................................................................................................24
8.1. libvirt Python スクリプトの作成要領......................................................................................................24
8.1.1. C 言語ライブラリとの対応.............................................................................................................24
8.1.2. スクリプトの流れ.............................................................................................................................25
8.2. スクリプトソースコード............................................................................................................................26
vattach......................................................................................................................................................26
vconsole...................................................................................................................................................27
vcreate......................................................................................................................................................28
vdestroy....................................................................................................................................................29
vdetach.....................................................................................................................................................30
functions.py..............................................................................................................................................31
vlist...........................................................................................................................................................33
vmigrate...................................................................................................................................................34
vrestore.....................................................................................................................................................35
vresume....................................................................................................................................................36
vsave........................................................................................................................................................37
vshutdown................................................................................................................................................38
vstats........................................................................................................................................................39
vsuspend...................................................................................................................................................40
1. はじめに
本書は、「OSS 仮想化機構 KVM についての調査」の一環で、KVM の基本機能について操作の手順および
注意すべき事項をまとめたものである。また、本書および当該調査の調査報告書に記述した操作を第三者が容
易に再現できるように、評価環境およびその構築方法についても記述している。
本書の構成を以下に示す。
•
第 2 章では、本検証における環境を説明し、その構築方法を示す。
•
第 3 章では、仮想マシンの操作のために必要な準備について説明する。
•
第 4 章では、仮想マシンの起動のために必要な作業と起動方法について説明する。
•
第 5 章では、起動した仮想マシンに対する様々な操作について、その操作方法と実際に動作して得られ
た知見について説明する。
•
第 6 章では、仮想マシンで使用するデバイスの定義方法や動的な制御方法について説明する。
•
第 7 章では、仮想マシンで使用するリソースの動的な変更について説明する。
•
第 8 章に libvirt を使用したプログラムの作成要領と本検証で用いたスクリプトのソースコードを示す。
-1-
2. 評価環境
2.1. システム構成
図 2-1:システム構成
図 2-1 に示すように、評価に用いたシステムは、仮想マシン(以下、VM)を実行する複数のノードとそれらを制
御するための一台の制御ノードからなる。ここで、制御ノード自身も他ノードと同様に VM を実行可能とした。
一般的にクラウド環境では多数のノードを使用するため、VM の操作の都度 VM を実行するノードにログインし
て操作することは非効率である。よって、制御ノードから集中的にシステム内の VM を操作する方式とした。
2.2. ネットワーク構成
図 2-2 にネットワーク構成を示す。「2.6.3. ネットワーク環境設定」では、この図の構成を再現する設定手順を説
明している。
図 2-2:ネットワーク構成
VM を全てのノードへ容易に配置可能かつ移動可能とするため、各ノードで動作する VM が同一セグメントに
属するようネットワークを構成した。各 VM にはプライベートな IP アドレス(IPv4)を与える。また、VLAN を利用して
VM 間で隔離されたプライベートなネットワークが構成できるようにした(図 2-2 中の eth0.10、br10)。
VM は、仮想 NIC をブリッジ br0 に接続することにより、物理マシン、システム内の VM と同一セグメント
(192.168.0.0/24) に存在するように見える(図 2-3)。
-2-
図 2-3:VM のネットワーク接続概念図
外部から VM へアクセス可能にするためには、少なくともひとつの VM が br0 側とのインタフェースを持つ必
要がある(図 2-4)。本評価環境ではインタフェースをひとつのみ定義しているが、プライベートネットワークの必要
数に応じて定義すればよい。
図 2-4:VM のネットワーク接続概念図(VLAN)
2.3. ストレージ構成
VM をすべてのノードで実行可能とするため、VM イメージなどの格納に共有ストレージを用意する。本評価環
境では制御ノードが NFS により共有ストレージを提供する。VM イメージは共有ストレージに配置し、各ノードから
NFS によりアクセスする。
2.4. 物理マシン構成
本評価環境の物理マシンの構成、スペックを以下図 2-5、表 2-1 に示す。
図 2-5:物理マシン構成
-3-
表 2-1:スペック一覧
ノード
モデル
CPU
メモリ
IPA-1
IPA-2
IPA-3
IPA-4
スイッチ
HP ML115 G5
HP ML115 G5
HP ML110 G5
HP ML110 G5
HP ProCurve 2510G (24
port)
AMD Opteron 1354
2.2GHz
2MB L2 Quad Core
AMD Opteron 1354
2.2GHz
2MB L2 Quad Core
4GB
4GB
4GB
4GB
-
SATA 160GB
SATA 160G
SATA 160GB
SATA 160GB
-
SATA 1500GB (×2)
-
-
-
-
NC105i
Gigabit Ethernet (eth0)
NC105i
Gigabit Ethernet
(eth0)
NC105i
Gigabit Ethernet (eth0)
NC105i
Gigabit Ethernet (eth0)
-
-
-
-
-
Intel Xeon X3210 2.13GHz Intel Xeon X3210 2.13GHz
2x4MB L2 Quad Core
2x4MB L2 Quad Core
-
ディスク
NIC
NC360T
Gigabit Ethernet
(dual port: eth1, eth2)
2.5. ベースシステム
CentOS 5.4 (x86_64 版)をホスト OS 及び VM で動作するゲスト OS として使用した1。KVM に関する主要な
パッケージを表 2-2 へ示す。
表 2-2:KVM 関連パッケージ
コンポーネント
パッケージ
カーネル
kernel-2.6.18-164.el5
KVM カーネルモジュール
kmod-kvm-83-105.el5_4.9
qemu
kvm-83-105.el5_4.9
libvirt
libvirt-0.6.3-20.1.el5_4
また、評価中に検出した障害の修正状況や、一部の機能の改善・拡張状況を Fedora 12 を用いて確認した。
Fedora 12 の KVM 関連パッケージを表 2-3 に示す。
表 2-3:KVM 関連パッケージ(Fedora12)
コンポーネント
パッケージ
カーネル(KVM を含む) kernel-2.6.31.5-127.fc12.x86_64
qemu
qemu-system-x86-0.11.0-12.fc12.x86_64
libvirt
libvirt-0.7.1-15.fc12.x86_64
2.6. システム構築
前節で示した評価環境を構築するための手順を説明する。
1 OS の選定理由に関しては『調査報告書』の「2.2.3. ソフトウェア構成」を参照。
-4-
2.6.1. インストール
CentOS 5.4(x86_64 版)を通常の手順でインストールする。パッケージグループの選択はデフォルトとした。初
回起動時の設定で、SELinux とファイアウォールを無効にした。追加で必要なパッケージを、以下のとおり yum コ
マンドを使用してインストールする。
# yum install kvm qemu libvirt libvirt-python
制御ノードでは、グラフィックを使用するため、以下のパッケージをインストールした。
# yum groupinstall 'X Window System' 'GNOME Desktop Environment'
2.6.2. BIOS 設定
KVM を使用するためには、仮想化支援機能を有する CPU が必須であり、同機能が有効化されている必要が
ある。同機能が有効であるかを確認するには、ホスト OS で/proc/cpuinfo を参照すればよい。
# cat /proc/cpuinfo | grep flags
flags
: fpu vme ... vmx ...
...
Intel の CPU では”vmx”が、AMD の CPU では”svm”が表示されるとよい。仮想化支援機能を備えた CPU に
上記の表示がない場合は、BIOS の設定で同機能を有効にする必要がある。本評価環境で使用したマシンの中
では、Intel マシン(HP ML110 G5)については、仮想化支援機能の出荷時設定が無効になっていたため、BIOS 設
定で有効にする必要があった。
2.6.3. ネットワーク環境設定
図 2-2 に示したネットワークを各ノードの起動時に設定するため、/etc/sysconfig/network-scripts 配下に次の
ファイルを作成する。
•
ifcfg-eth0
DEVICE=eth0
BOOTPROTO=none
HWADDR=00:25:B3:E6:7A:7A
ONBOOT=yes
BRIDGE=br0
•
ifcfg-br0
DEVICE=br0
TYPE=Bridge
BOOTPROTO=static
BROADCAST=192.168.0.255
IPADDR=192.168.0.1
IPV6INIT=yes
IPV6_AUTOCONF=yes
NETMASK=255.255.255.0
NETWORK=192.168.0.0
ONBOOT=yes
DELAY=0
•
ifcfg-eth0.10
DEVICE=eth0.10
BOOTPROTO=none
ONBOOT=yes
BRIDGE=br10
•
ifcfg-br10
DEVICE=br10
TYPE=Bridge
BOOTPROTO=none
ONBOOT=yes
DELAY=0
-5-
上記は、IPA-1 の設定例である。他のノードでは、ifcfg-eth0 の HWADDR、ifcfg-br0 の IPADDR のみを変更す
ればよい。なお、IPA-1 の eth1 側の設定は割愛する。
ネットワークに関して設定が必要なファイルを以下に示す。
•
/etc/sysconfig/network
VLAN=yes
GATEWAY=192.168.0.1
#制御ノードのIPアドレス
“VLAN=yes”は、VLAN を使用するために必要である。上記の GATEWAY の設定値は、制御ノード以
外での設定内容である。制御ノードの GATEWAY は、ネットワーク環境に応じて設定する。
•
/etc/sysctl.conf
net.ipv4.ip_forward = 1
ブリッジを使用するために必要な設定である。
2.6.4. その他環境設定
本評価環境では、VM の IP アドレスを DHCP で割り当てるため、制御ノードを DHCP サーバかつ DNS サーバ
とした。 以下に、制御ノードに行った設定手順を示す。
•
dnsmasq パッケージをインストールし、ノード起動時にサーバプログラムが起動する設定とする。
# yum install dnsmasq
# chkconfig dnsmasq on
•
/etc/dnsmasq.conf を編集し、dnsmasaq の設定を行う。
interface=br0
dhcp-range=192.168.0.50,192.168.0.150,255.255.255.0,infinite
•
VM のセグメント(192.168.0.0/24)から外へのアクセスができるように NAT の設定を行っている。
# iptables -t nat -A POSTROUTING -o eth1 -s 192.168.0.0/24 -j MASQUERADE
# service iptables save
2行目の処理により、/etc/sysconfig/iptables に設定が保存され、ノード起動時に自動的に設定される。
制御ノード以外のノードは、制御ノードを DNS サーバとするため、/etc/resolve.conf を以下のとおり編集する。制
御ノードでは、ネットワーク環境に応じて DNS サーバを設定する。
nameserver 192.168.0.1
このほか、制御ノードには NFS サーバの設定を行った。NFS サーバの設定方法は一般的であるため、説明を
割愛する。
-6-
3. 使用準備
3.1. 使用ツール
KVM では、Xen と異なり VM の操作のための専用コマンド2は用意されていない。VM の起動には、qemu-kvm
コマンド(以下、qemu)を使用するが、VM の定義ファイルではなく、コマンドラインで VM のパラメータを指定する。
VM の操作には、qemu モニタと呼ばれる通信チャネルを通して、qemu プロセスとインタラクティブにやり取りをす
る必要があり、クラウド環境下での管理には向いていない。
そこで、VM の操作に libvirt を使用する。libvirt は、ハイパーバイザの操作を抽象化して提供する C 言語ライ
ブラリである。コマンドラインツールの virsh と、Python など各種言語へのバインディングが提供されている。virsh
を VM の操作コマンドとして使用することもできるが、用途に合ったスクリプトをスクリプト言語を用いて作成する
方が機能性や柔軟性、拡張性などの点で有利である。本書では、VM 操作のためのスクリプトを Python で作成
して使用した。Python によるスクリプト作成の要領と、本書で使用するスクリプトのソースコードを「8. 添付資料」
に示した。
3.2. libvirt 使用準備
本評価環境で libvirt を使用するために、予め必要な作業について説明する。
3.2.1. サービスの起動設定
全ノードで以下を実行する。
# chkconfig libvirtd on
3.2.2. 設定ファイル
libvirt の設定ファイルに、/etc/sysconfig/libvirtd と/etc/libvirt/libvirtd.conf があるが、どちらもデフォルト設定か
ら変更する必要はない。
3.2.3. ネットワーク設定
libvirt は様々なネットワーク構成をサポートしているが、本評価環境では、libvirt のネットワーク構成に関する機
能は使用しない。libvirt では、最初から default ネットワーク(ローカルマシン内で NAT を用いたネットワークを構
成する)が有効になるように設定されている。default ネットワークは、本評価環境のネットワーク設定と干渉するた
め、以下のコマンドにより使用を抑止しておく必要がある。
# virsh net-autostart default --disable
これは、最初に一回実行しておけばよい。ただし、コマンド実行後は一度ノードを再起動する必要がある。
3.2.4. リモート接続準備
本評価環境では、制御ノードからノードへの接続に、設定の単純さから ssh を用いている3。接続時のパスワード
入力を不要とするため以下の作業を行った。
2 Xen には xm という専用の VM の操作・管理コマンドが用意されている。
3 libvirt には、他の通信方式として、TLS や unix ドメインソケット等を利用することができる。参考 URL:
http://libvirt.org/remote.html
-7-
•
制御ノードで以下のコマンドを実行し、公開鍵を作成する。
# cd /root/.ssh
# ssh-keygen
•
各ノードで、上記で作成したファイルの内容を authorized_keys ファイルに追加する。
# cat id_rsa.pub >> /root/.ssh/authorized_keys
•
制御ノードから各ノードに一度ログインすることにより、ノードの情報が/root/.ssh/known_hosts へ記録さ
れる。
3.3. スクリプト使用準備
vfunctions.py ファイルにノードのホスト名と URI の一覧を定義してある。定義例を以下に示す。
host_uri = [("localhost", "qemu:///system"),
("ipa2", "qemu+ssh://ipa2/system"),
("ipa3", "qemu+ssh://ipa3/system"),
("ipa4", "xen+ssh://ipa4/")]
この例では、ipa4 に Xen の場合の定義がなされている。本書で使用しているスクリプトは Xen 環境でも動作する
ことを確認している。
-8-
4. VM の起動
4.1. VM の定義
libvirt では VM をドメインと表現し、VM を定義するために XML ファイルを用いる。それに倣い、本書では VM
を定義する XML ファイルをドメイン定義 XML と呼ぶ。
以下に典型的な定義例を示す。本書ではこれをテンプレートとして使用する。定義内容や変更が必要な箇所
については、後の説明の中で触れていく。
<domain type='kvm'>
<name>work-64-1</name>
<uuid>70a65ea4-e0d6-476e-b892-9a90389e3473</uuid>
<memory>1048576</memory>
<currentMemory>1048576</currentMemory>
<vcpu>1</vcpu>
<os>
<type arch='x86_64'>hvm</type>
<boot dev='hd'/>
</os>
<features>
<acpi/>
</features>
<clock offset='utc'/>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>destroy</on_crash>
<devices>
<emulator>/usr/libexec/qemu-kvm</emulator>
<disk type='file' device='disk'>
<source file='/data/images/work-64-1.img'/>
<target dev='vda' bus='virtio'/>
</disk>
<interface type='bridge'>
<source bridge='br0'/>
<mac address='00:00:00:03:00:03'/>
<model type='virtio'/>
</interface>
<graphics type='vnc' port='5900' listen='0.0.0.0' autoport='yes' keymap='ja'/>
</devices>
</domain>
4.2. VM イメージの作成
VM を起動して、物理マシンと同様にインストールを行うのが最も普通の方法である。新規のイメージファイル
の作成には、dd コマンドを使用する。以下に 4GB のディスクイメージを作成する例を示す。
# dd if=/dev/zero of=vm.img bs=1M count=4096
イメージファイルのタイプは、raw 形式で領域を事前に割り当てておくことを推奨する。そのため、qemu-img コ
マンドではなく、dd コマンドの使用を推奨する。
既存のイメージファイルをコピーして作成する場合は、コピー先のファイルがスパースファイルとならないよう、
dd コマンドを使用する、あるいは cp コマンドに--sparse=never をオプションに与えコピーする。IP アドレスなど VM
の設定に変更が必要な場合は、ループバックマウントして修正すればよい。
-9-
4.3. VM の起動
4.3.1. 実行形式
•
書式
vcreate [-v] [-c host] domain-xml
•
説明
domain-xml に指定するドメイン定義 XML で定義された VM を起動する。
•
オプション
-v
起動と同時に VNC コンソールを開く。
-c host
VM を実行するホスト名を指定する。省略するとローカルホストを対象とする。
4.3.2. ドメイン定義 XML
テンプレートからの変更ポイントを以下に説明する。
•
<name>
VM 名(VM に一意の名前)を指定する。
•
<uuid>
VM の uuid(VM に一意の id)を指定する。
•
<memory>
VM に割り当てるメモリ量(KB)を指定する。
•
<currentMemory>
VM の起動時に割り当てるメモリ量(KB)を指定する。この値は、balloon ドライバをサポートしているゲス
ト OS にしか意味を持たない。ゲスト OS が balloon ドライバをサポートしていない場合は、固定的に
<memory>で指定した値となる。
•
<vcpu>
VM の VCPU 数を指定する。
•
<os>
テンプレートは、ゲスト OS が 64bit であることを想定している。32bit の場合は、
<type arch='i686'>hvm</type>とする。
テンプレートはハードディスクよりブートすることを想定している。cdrom からブートさせる場合は、
<boot dev='cdrom'/>とする。<boot>要素は複数定義可能で、定義した順に起動が試みられる。
•
<features>
ゲスト OS が 32bit の場合は、<pae/>を定義する。
•
<disk>、<interface>
必要な分だけ定義する。定義の詳細は、デバイス制御の節を参照されたい。
- 10 -
4.3.3. インストール時の起動方法
VM のインストールは、物理マシンのインストールと同様にインストール DVD から起動して行うことができる。
ここでは、その際のドメイン定義 XML の設定要領を示す。
インストール DVD 用の<disk>定義と cdrom から boot を行う<boot>定義を追加する。テンプレートからの変更
部分(抜粋)を以下に示す。
...
<os>
<type arch='x86_64'>hvm</type>
<boot dev='hd'/>
<boot dev='cdrom'/>
</os>
...
<disk type='file' device='disk'>
<source file='/data/images/work-64-1.img'/>
<target dev='vda' bus='virtio'/>
</disk>
<disk type='file' device='cdrom'>
<source file='/data/iso/CentOS-5.4-x86_64-bin-DVD.iso'/>
<target dev='hdc' bus='ide'/>
<readonly/>
</disk>
...
boot の順は、hd、cdrom の順にしておくとよい。初回の起動時は、ハードディスクイメージに OS がインストール
されていないため、cdrom から起動されインストールが開始される。インストール終了後の再起動時は、hd から
ブートされる。 仮想ドライブのメディアを入れ替えるためには、qemu モニタを通して仮想ドライブの切断・再接続
が必要となり作業が煩雑となるため、インストールメディアが一枚で済むよう DVD イメージを用いるとよい。
- 11 -
5. VM のライフサイクル制御
本章では、VM を起動した後の様々な操作について説明する。
5.1. VM の停止
5.1.1. 実行形式
•
書式
vshutdown [-c host] name
•
説明
name に指定する VM に対して shutdown の実行を促す。vshutdown は、VM に shutdown の実行を促し
復帰する。shutdown の実行状況を関知せず、shutdown の完了を待たない。
•
オプション
-c host
VM が実行されているホスト名を指定する。省略時は全ホストから VM を探す。VM が起動されている
ホストが事前にわかる場合は、指定する方が高速に動作する。
5.1.2. 処理補足
vshutdown を用いずに、ゲスト OS 内でシャットダウン処理を実行する方法でも、正常に VM を停止できる。
vshutdown は、外部から正常な停止を促すための手段である。
shutdown 実行後の動作は、ゲスト OS の環境に依存する。例えば、ゲスト OS が CentOS 5.4 の場合、グラ
フィックコンソールにログインした状態では、シャットダウンするかどうかのダイアログが出力され、インタラクティ
ブな処理が要求される。グラフィックコンソールを使用していないか、コンソールを開いていない状態の場合は、
シャットダウン処理が実行される。
VM へのシャットダウンイベントの通知は、ACPI のパワーダウンイベントを通して行われるため、ACPI のエミュ
レーションが必要である。そのため、テンプレートに示すように<features>に<acpi/>を設定しておく必要がある。
<acpi/>が設定されていない場合は、vshutdown は後述の vdestroy と同様に、VM を強制終了させることに注意
されたい。
シャットダウン処理終了後、VM の動作は終了し、物理マシンでの電源断と同等の状態となる。<acpi/>が設定
されてない場合は、ゲスト OS 内からシャットダウンを実行した場合でも、電源断状態にならないため注意が必要
となる。つまり、ゲスト OS でシャットダウン処理を行うとゲスト OS は停止する(コンソールに「System halted.」の
メッセージが出力される)が、VM は終了しない。CPU は消費しないものの、libvirt からみると running のままとな
る。この状態から VM を終了させるためには、vdestroy を実行する必要がある。
このように注意事項が多くなるため、<acpi/>を設定しておくことを推奨する。
- 12 -
5.2. VM の強制停止
5.2.1. 実行形式
•
書式
vdestroy [-c host] name
•
説明
name に指定する VM を強制停止する。物理マシンで電源を落とした状態と同等の状況となる。
•
オプション
-c host
VM が実行されているホスト名を指定する。省略時は全ホストを探す。VM が起動されているホストが事
前にわかる場合は、指定する方が高速に動作する。
5.2.2. 処理補足
即座に VM は終了する。ゲスト OS からは、突然電源断された場合と同等である。ゲスト OS がハングアップし
た状態でも確実に VM を終了させることができる。
5.3. VM の再起動
5.3.1. 処理補足
libvirt には、VM の再起動を行う virDomainReboot インタフェースが用意されているが、KVM ではそのインタ
フェースがサポートされていない。したがって、ゲスト OS 内で reboot を実行する以外に VM を再起動させる方法
はない。
reboot した場合、VM に対応する qemu プロセスの動作は終了することなく継続される4。つまり、qemu プロセス
が使用していたメモリ等のリソースが解放されない。リソースを解放するためには、VM を一度停止し、再び起動
する必要がある。なお、ドメイン定義 XML で、<on_reboot>の設定を destroy にしておくと、ゲスト OS で reboot を
実行したときに、シャットダウン処理終了後、VM は、reboot せずに終了する。
5.4. VM の一時停止、再開
5.4.1. 実行形式
•
書式
vsuspend [-c host] name
vresume [-c host] name
•
説明
vsuspend は、name に指定する VM を一時停止する。vresume は、一時停止している VM の実行を再開
する。
4 Xen 環境での reboot は VM が一旦終了し再び VM が生成されるため別ドメインとなり、KVM とは挙動が異
なる。
- 13 -
•
オプション
-c host
VM が実行されているホスト名を指定する。省略時は全ホストを探す。VM が起動されているホストが事
前にわかる場合は、指定する方が高速に動作する。
5.4.2. 処理補足
vsuspend を実行すると、qemu プロセスは動作を停止し CPU の消費をやめる。すなわち、VM の実行は停止さ
れ、外部からはゲスト OS がハングアップした状態と同等に見える。libvirt が管理する VM の状態は、一時停止
中(paused)になる。したがって、vlist で VM の状態を確認することにより、一時停止中と OS ハングアップを区別で
きる。
なお、vresume は、libvirt が管理する VM の状態が paused の VM にのみ効果がある。
5.5. VM の保存、復元
5.5.1. 実行形式
•
書式
vsave name save-dir/name
vrestore [-v] [-c host] save-dir/name
•
説明
vsave は、name に指定する VM の状態をファイルに保存し、VM を停止させる。ファイル名は、VM 名と
同一にしておく必要がある。vrestore は、保存したファイルから VM の状態を復元し、VM を起動する。
VM は、停止した時点から再開される。
•
オプション
-v
起動と同時に VNC コンソールを開く。
-c host
VM を実行するホスト名を指定する。省略するとローカルホストを対象とする。
5.5.2. 処理補足
本検証では、VM の状態保存ファイルを共有ストレージに格納し、どのノードにおいても復元、再開可能である
ことを確認した。ネットワーク接続の再開についても問題ない5。復元までの時間が長時間になる場合、ネットワー
ク接続について、ゲスト OS 上のアプリケーションレベルで考慮する必要がある。VM を単に移動する目的では、
vmigrate を使用した方がよい。
VM 復元後のゲスト OS の時刻は、保存時点の時刻から計時が再開されることに注意が必要である。すなわち、
保存から長時間経過後に復元する場合、正しい時刻から大きく遅れることとなる。アプリケーションによっては不
具合を生じる可能性があるため、復元後に時刻を合わせる必要がある。
5 NIC モデルに rtl8139 を使用する場合、復元後のネットワーク接続が再開しないケースが見られた。その場合、
ゲスト OS 上でネットワークサービスの再起動をする必要がある。
- 14 -
5.6. VM の移動
5.6.1. 実行形式
•
書式
vmigrate [-l] [-v] [-c host] name dest
•
説明
vmigrate は、name で指定する VM をホスト dest に移動する。dest は、VM が実行中のホストとは別のホ
ストを指定しなければならない。
•
オプション
-l
ライブマイグレーションを行う。
-v
移動後 VNC コンソールを開く。
-c host
移動前に VM が実行されているホスト名を指定する。省略時は全ホストを探す。VM が起動されている
ホストが事前にわかる場合は、指定する方が高速に動作する。
5.6.2. 処理補足
-l オプションを指定しなければ、vmigrate を実行すると VM は移動が完了するまで状態が一時停止中
(paused)となる。VNC コンソールは、移動時にクローズされる。
qemu では、移動先をホスト名で認識するため、移動先のホスト名(移動先で hostname コマンドで表示される
名前)が移動元で名前解決できる必要がある。
本検証環境では、同じ CPU タイプのマシン同士では、安定してライブマイグレーションが動作した。しかし、
Intel マシンと AMD マシン間では、qemu が異常終了する場合があった6。
ライブマイグレーションの実行中、libvirtd が別の管理要求に対して応答を受け付けないタイミングがあるが、
実行中の移動処理が終了すれば応答を再開する。
5.7. VM の情報取得(1)
5.7.1. 実行形式
•
書式
vlist [-c host | -a]
•
説明
vlist は、実行している VM の一覧を表示する。表示形式は以下のとおり。
host: id name state vnc-port ip-addr
6 コミュニティに報告済み(http://www.mail-archive.com/[email protected]/msg34297.html )。同条件で正
しく動作する場合もあり、再現性は不明。
- 15 -
‣
host
VM を実行しているホスト
‣
id
VM の ID
‣
name
VM 名
‣
state
VM の状態。以下の状態がある。

no-state: 状態なし

running: 実行中

blocked: CPU スケジューリング待ち

paused: 一時停止中

in-shutdown: 停止処理中

shutdown: 停止した状態

crashed: クラッシュした状態
ただし、KVM の場合は、「running」と「paused」のみが用いられる。
‣
vnc-port
VNC コンソールのポート番号
‣
ip-addr
VM の IP アドレス
•
オプション
-c host
指定したホストで実行されている VM の一覧を表示する。
-a
すべてのホストで実行されている VM の一覧を表示する。-c も -a も指定しなかったときは、ローカルで
実行されている VM の一覧を表示する。
5.7.2. 処理補足
id、ドメイン名、ドメインの状態などは、virDomain オブジェクトにそれらを個々に取得できるメソッドがあるが、
virDomain::XMLDesc メソッドを用いれば一括して取得できる。XMLDesc メソッドで取得する XML は、ドメイン
定義 XML の内容に加えて、VM 起動時に割り当てられたリソースの情報が付加されている。付加されている情
報には、以下のようなものがある。
•
ドメイン id
•
ネットワークインタフェース名
•
VNC コンソールのポート番号
なお、これらの値はホスト内では一意であるが、システム全体では一意ではない。
- 16 -
vlist コマンドでは、VM の IP アドレス(eth0 のみ)を表示している。ゲスト OS の IP アドレスを知る一般的な方法
はないが、本検証環境では制御ノードで動作している dnsmasq から DHCP でアドレスを取得するため、dnsmasq
のリースファイルを参照し、IP アドレスを取得している。
5.8. VM の情報取得(2)
5.8.1. 実行形式
•
書式
vstats [-c host] name
•
説明
vstats は、name に指定する VM のリソース使用状況を表示する。vstats の出力例を以下に示す。
max memory: 1024 MB
current memory: 1024 MB
num vcpu: 1
cpu usage: 23.50000000 sec
hda: rd_req = 4700, rd_bytes = 26507776, wr_req = 926, wr_bytes = 12615680
vnet0: rx_bytes = 1733084, rx_packets = 2432, rx_errs = 0, rx_drop = 0, tx_bytes = 12039,
tx_packets = 91, tx_errs = 0, tx_drop = 0
表示内容は、以下のとおりである。
‣
max memory
VM に割り当て可能な最大メモリ量
‣
current memory
VM に現在割り当てられているメモリ量
‣
num vcpu
VM の VCPU 数
‣
ディスクデバイス名:統計情報
VM に接続されているディスクデバイス毎に、下記の統計情報を表示する
‣
⁃
総リード要求数
⁃
総リードバイト数
⁃
総ライト要求数
⁃
総ライトバイト数
ネットワークインタフェース名:統計情報
VM に接続されているネットワークインタフェース毎に下記の統計情報を表示する
⁃
総受信バイト数
⁃
総受信パケット数
⁃
総受信エラー数
⁃
総受信パケットドロップ数
⁃
総送信バイト数
- 17 -
•
⁃
総送信パケット数
⁃
総送信エラー数
⁃
総送信パケットドロップ数
オプション
-c host
VM が実行されているホスト名を指定する。省略時は全ホストを探す。VM が起動されているホストが事
前にわかる場合は、指定する方が高速に動作する。
5.8.2. 処理補足
CPU 使用量は、virDomain::info メソッドで取得している。取得した値は、qemu プロセスを ps コマンドで取得で
きる値と等しい。
ディスクの統計情報は、各ディスクデバイスに対して virDomain::blockStats メソッドで取得している。libvirt は
qemu モニタから当該情報を取得している。
ネットワークの統計情報は、各ネットワークインタフェースに対して virDomain::interfaceStats メソッドで取得し
ている。libvirt は、tap デバイス名を元にホスト OS の/proc ファイルシステムから当該情報を取得している。
- 18 -
6. デバイスの制御
6.1. ディスクの定義
ドメイン定義 XML の中のディスク定義について説明する。いくつか指定のバリエーションがあるので、それぞ
れについて指定方法を示す。
6.1.1. デバイスのタイプ
<disk>要素の device 属性で指定する。ディスク(‘disk’)または、cd-rom(‘cdrom’)が指定できる。
•
ディスクの例
<disk type='file' device='disk'>
<source file='/data/images/work-64-1.img'/>
<target dev='hda' bus='ide'/>
</disk>
•
cd-rom の例
<disk type='block' device='cdrom'>
<source dev='/dev/cdrom'/>
<target dev='hdc' bus='ide'/>
</disk>
6.1.2. ソースファイルのタイプ
通常ファイルか特殊ファイルかにより、<disk>要素の type 属性と<source>要素の属性が異なる。以下に設定例
を示す。
•
通常ファイルの例
<disk type='file' device='cdrom'>
<source file='/data/images/work-64-1.iso'/>
<target dev='hdc' bus='ide'/>
</disk>
•
特殊ファイルの例
<disk type='block' device='disk'>
<source dev='/dev/loop1'/>
<target dev='vda' bus='virtio'/>
</disk>
6.1.3. インタフェースタイプ
インタフェースタイプとして、ide と virtio が指定可能である。ただし、virtio はゲスト OS が virtio に対応している
必要がある。インタフェースタイプは、<target>要素で指定する。ターゲットデバイス名は、ide の場合、hda、hdb、
…を使用する。virtio の場合は、vda、vdb、…を使用する。ターゲットデバイス名は順番に指定する必要があり、vda
の次に vdc を使用することはできない7。
•
ide の例
<disk type='file' device='disk'>
<source file='/data/images/work-64-1.img'/>
<target dev='hda' bus='ide'/>
</disk>
•
virtio の例
<disk type='file' device='disk'>
7 libvirt が連続したデバイス名を前提としているため。
- 19 -
<source file='/data/images/work-64-1.img'/>
<target dev='vda' bus='virtio'/>
</disk>
性能面から、ゲスト OS が virtio をサポートしている場合は、virtio の使用を推奨する。CentOS 5.4 がゲスト OS
の場合、virtio はサポートされている。
なお、Fedora 12 ではこのほかに scsi を指定できるが、CentOS 5.4 ではサポートされていない。
6.2. ディスクの動的追加・削除
インタフェースタイプとして virtio を使用すると、VM に対して動的にディスクの追加、削除ができる。そのため
のスクリプトを以下で説明する。
6.2.1. 実行形式
•
書式
vattach [-c host] name device-xml
vdetach [-c host] name device-xml
•
説明
vattach は、name に指定する VM に device-xml ファイルで定義されるデバイスを追加する。
vdetach は、name に指定する VM から device-xml ファイルで定義されるデバイスを取り外す。
device-xml ファイル(デバイス定義 XML ファイル)に追加・削除するデバイスを定義する。
•
オプション
-c host
VM が実行されているホスト名を指定する。省略時は全ホストを探す。VM が起動されているホストが事
前にわかる場合は、指定する方が高速に動作する。
6.2.2. 処理補足
デバイス定義 XML ファイルの中にはひとつのディスク定義を記述する。デバイス名が(vda、vdb、…)が連続す
るよう管理する必要があるため、追加、削除の際は注意されたい。
VM はデバイスの追加・削除を、ACPI の PCI ホットプラグインタフェースを通して認識する。したがって、
<features>要素の<acpi/>定義が必須である。
ゲスト OS として CentOS 5.4 を使用する場合、ゲスト OS であらかじめ、acpiphp カーネルモジュールをロードし
ておく必要がある。acpiphp カーネルモジュールは ACPI の PCI ホットプラグをサポートするものである。ゲスト OS
として Fedora 12 を使用する場合は、acpiphp は静的にカーネルに組み込まれており、事前の対処は必要ない。
Fedora12 をホスト OS として使用した場合は、インタフェースタイプとして scsi を使用した場合でも、ディスクの
動的追加・削除が可能である。
6.3. ネットワークインタフェースの定義
ドメイン定義 XML の中のネットワークインタフェース定義について、考慮すべき事項について説明する。
- 20 -
6.3.1. ネットワークタイプ
VM のネットワーク構成にはいくつかの種類があるが、本評価環境においてはブリッジ構成のみを利用した。
<interface>要素の type 属性には、’bridge’を指定し、<source>要素で接続するブリッジ名を指定する。以下に定
義例を示す。
<interface type='bridge'>
<source bridge='br0'/>
<mac address='00:00:00:03:00:03'/>
<model type='virtio'/>
</interface>
6.3.2. MAC アドレス
本評価環境では、MAC アドレスは、全 VM 定義の全 NIC 定義で一意にしておく必要がある。
6.3.3. NIC モデル
<model>要素の type 属性で、使用する NIC のモデルを指定できる。指定可能なモデルを以下に示す。
"ne2k_pci","i82551","i82557b","i82559er","rtl8139","e1000","pcnet","virtio"
準仮想化ドライバである virtio 以外は、指定したモデルのエミュレーションとなる。<model>要素を省略すると
rtl8139(Realtek の NIC)となる。性能面から、virtio をサポートしているゲスト OS に対しては、virtio を推奨する。ゲ
スト OS として、CentOS 5.4 を使用する場合は、virtio が使用可能である。デフォルトの rtl8139 はファストイーサ
ネット(100Mbps)である。e1000 などのギガビットイーサネット(1Gbps)のエミュレーションの方が高性能で動作す
る。
6.4. ネットワークインタフェースの動的追加・削除
CentOS 5.4 では、libvirt が未対応である。qemu の機能としてはサポートされており、libvirt を新しいものに置き
換えれば、実行可能である。Fedora 12 の libvirt ではサポートされている。
本検証では、ホスト OS に Fedora 12、ゲスト OS に CentOS 5.4 を用いて動作を確認した。ディスクの場合と同
様に、vattach、vdetach スクリプトを使用して、ネットワークインタフェースの動的追加・削除ができる。追加・削除
するネットワークインタフェースを定義したデバイス定義 XML ファイルをコマンド引数に与えるとよい。
6.5. コンソールの定義
VM のコンソールとしては、SDL、VNC、またはシリアルコンソールが選択可能である。本検証では、制御ノード
からすべての VM へのアクセスに最も利便性が高い VNC を使用する8。
VNC コンソールの定義は、テンプレートから変更する必要はない。以下に定義部分を再掲する。
<graphics type='vnc' port='5900' listen='0.0.0.0' autoport='yes' keymap='ja'/>
シリアルコンソールは、コンソール出力をファイルに出力することができるため、障害時の解析に有用である。
参考のため、以下に定義例を示す。
<serial type='file'>
<source path='/var/log/vm-conole/work-64-1.log'/>
</serial>
8 SDL、シリアルコンソールは、ホストノード以外からのリモートアクセスができない、または単純ではない課題が
ある。VNC ではリモートアクセスが可能であり、ゲスト OS が Windows の場合でも容易に利用できる。
- 21 -
出力するファイルは、VM の作成のつど新規作成される。同じパス名を使用すると最後に起動した VM がファ
イルを上書きすることに注意が必要である。
また、ゲスト OS が Linux の場合、カーネルパラメータにシリアルコンソールへの出力を追加しておく必要がある
(例:console=tty0 console=ttyS0 を追加)。
6.6. Windows ゲストの PV ドライバ
ディスク、ネットワークインタフェースとも性能面から virtio を使用することが望ましい。ゲスト OS として CentOS
5.4 を使用する場合、virtio は標準でサポートされている。
ゲスト OS として Windows を使用する場合、ネットワークインタフェースに関しては、Windows 用の PV ドライバ
が用意されている。以下に参考 URL を示す。
http://www.linux-kvm.com/content/tip-how-setup-windows-guest-paravirtual-network-drivers
なお、Red Hat Enterprise Linux 5.4 では、virtio-win パッケージが用意されており、ディスク、ネットワークインタ
フェースとも virtio が使用可能となっている。このパッケージは、Red Hat Network からダウンロード可能である。
このパッケージのソースコードは公開されていない。
- 22 -
7. 動的なリソース変更
7.1. メモリ
balloon ドライバをサポートしているゲスト OS では、メモリの動的増減ができる。CentOS 5.4 では ballon ドライ
バをサポートしていないが、Fedora 12 ではサポートされている。ホスト OS としては CentOS 5.4 でも動作可能で
ある。
メモリ量は、<memory>で指定した値が最大値となり、それ以上の増加はできない。メモリの増減は、virsh
setmem コマンドにより実行できる9。VM のメモリ量の変化は、vstats コマンド の current memory の値で確認でき
る。また、ゲスト OS 上からは/proc/meminfo により増減が確認でき、ゲスト OS からみると物理メモリ量が変化した
ように見える。
ホスト OS に CentOS 5.4、ゲスト OS に Fedora 12 を用いて動作を確認し、以下のような問題を検出した。
•
メモリを減少させる場合、極端に小さい値を指定すると、ゲスト OS がハングアップする。ping は通るが、
ログインはできず、CPU 時間が増加し続けた。この状態から、virsh setmem で再びメモリ量を増加させる
こともできない。
•
増減を繰り返していると、ゲスト OS 内の/proc/meminfo の値が異常となる。
したがって、現状は使用を控えておいた方がよいと考えられる。
7.2. CPU
VCPU 数の増減は qemu のレベルでサポートされていない。
9 メモリの増減を他の評価で行わないため、スクリプトは用意していない。
- 23 -
8. 添付資料
8.1. libvirt Python スクリプトの作成要領
ここでは、ソースコードの理解の助けとなるよう、libvirt の Python バインディングを用いたスクリプトの作成要
領を説明する。より詳細な情報は、以下に示す libvirt の公式サイトを参照されたい。
http://www.libvirt.org
8.1.1. C 言語ライブラリとの対応
libvirt は、C 言語のライブラリであり、ドキュメントも C 言語のライブラリ関数について記述されている。
Python バインディングで用意されているクラス、メソッドは、C 言語ライブラリから、ほぼ機械的に対応したもの
となっており、C 言語ライブラリのドキュメントを参照しながらプログラミングすることができる。以下に C 言語ライ
ブラリと Python バインディングのクラス、メソッドとの対応規則を示す。
•
•
•
virConnect 構造体が virConnect クラスに、virDomain 構造体が virDomain クラスに対応している。
関数の第一引数が virConnect 構造体ポインタであるライブラリ関数は、virConnect クラスのメソッドとし
て用意されている。また、関数の第一引数が virDomain 構造体ポインタであるライブラリ関数は、
virDomain クラスのメソッドとして用意されている。
メソッド名は、ライブラリ関数の先頭の「virConnect」「virDomain」を省略したものとなっている。また、属
性を取得するような関数に関しては、「Get」も省略されることがある。メソッド名の先頭は、小文字になる
(例外もある)。
表 8-1 に対応例をいくつか示す。
表 8-1:C 言語と Python の対応例
C 言語ライブラリ
クラス::メソッド
virConnectLookupByName(virConnectPtr, ...)
virConnect::lookupByName
virDomainCreateXML(virConnectPtr, ...)
virConnect::createXML
virDomainAttachDevice(virDomainPtr, ...)
virDomain::attachDevice
virDomainGetID(virDoaminPtr, ...)
virDomain::ID
virDomainGetName(virDomainPtr, ...)
virDomain::name
用意されているクラスとメソッドの一覧は、libvirt-python パッケージに入っている文書 libvirtclass.txt
(/usr/share/libvirt-python-0.6.3/libvirtclass.txt) を参照するとよい。また、メソッドの返り値、引数の詳細については、
libvirt.py (/usr/lib64/python2.6/site-packages/libvirt.py)を参照するとよい。
- 24 -
8.1.2. スクリプトの流れ
簡単なスクリプト例により、スクリプトの流れについて説明する。
以下は、ローカルノードで実行している VM の ID と名前を表示するスクリプトである。
import libvirt
uri = "qemu:///system"
conn = libvirt.openReadOnly(uri)
ids = conn.listDomainsID()
for id in ids:
dom = conn.lookupByID(id)
print "%d %s" % (dom.ID(), dom.name())
①
①
②
③
④
⑤
libvirt モジュールを import する。
② virConnect クラスのオブジェクトを取得する。ドメインの操作を行わない場合は、libvirt モジュールの
openReadOnly メソッドを使用する。openReadOnly メソッドの引数は、接続 URI を示す。
③ virConnect オブジェクトの listDomainsID メソッドを使用して、実行中のドメインの ID(配列)を取得する。
④
取得した ID に対応するドメインの virDomain オブジェクトを取得する。
⑤ virDomain クラスの ID メソッド、name メソッドで、ドメインの ID と名前を取得する。
以下は、ドメインの作成を行うスクリプトである。
import libvirt
import sys
xml_config = open(sys.argv[1]).read()
conn = libvirt.open("qemu:///system")
dom = conn.createXML(xml_config, 0)
print "%d %s" % (dom.ID(), dom.name())
①
②
①
ドメインの操作を行う場合は、libvirt モジュールの open メソッドを使用して virConnect オブジェクトを取
得する。
②
virConnect クラスの createXML メソッドを使用して、ドメインを作成する。
上記に示したように基本的な流れは、以下のようになる。
(1) libvirt.open (または、openReadOnly)メソッドを使用して、virConnect オブジェクトを取得する。
(2) virConnect オブジェクトのメソッドを使用して各種の操作(例えば、virDomain オブジェクトの取得)を行
う。
(3) virDomain オブジェクトのメソッドを使用してドメインに関する各種の操作を行う。
上記のスクリプトは、流れを説明する目的で、エラー処理は省略しているので注意されたい。
- 25 -
8.2. スクリプトソースコード
vattach
#!/usr/bin/python
import libvirt
import sys
import os
from optparse import OptionParser
from vfunctions import find_dom_by_name
usage = "usage: vattach [-c host] name xml_config"
parser = OptionParser(usage)
parser.add_option("-c", action="store", dest="host", help="host to be connected")
(options, args) = parser.parse_args()
if len(args) != 2:
parser.error("no name or xml_config")
name = args[0]
try:
xml_config = open(args[1]).read()
except:
print "open or read %s failed." % (args[1])
sys.exit(1)
dom, conn, h = find_dom_by_name(name, options.host)
if dom == None:
print "%s not found" % (name)
sys.exit(1)
try:
dom.attachDevice(xml_config)
except:
print "attachDevice failed"
sys.exit(1)
conn.close()
- 26 -
vconsole
#!/usr/bin/python
import libvirt
import sys
import os
from optparse import OptionParser
from xml.dom.minidom import parseString
from vfunctions import run_vncviewer, find_dom_by_name
usage = "usage: vconsole [-c host] name"
parser = OptionParser(usage)
parser.add_option("-c", action="store", dest="host", help="host to be connected")
(options, args) = parser.parse_args()
if len(args) != 1:
parser.error("no name")
name = args[0]
dom, conn, h = find_dom_by_name(name, options.host)
if dom == None:
print "%s not found" % (name)
sys.exit(1)
run_vncviewer(dom, h)
conn.close()
- 27 -
vcreate
#!/usr/bin/python
import libvirt
import sys
import os
from optparse import OptionParser
from xml.dom.minidom import parseString
from vfunctions import get_uri, run_vncviewer
usage = "usage: vcreate [-v] [-c host] xml_config"
parser = OptionParser(usage)
parser.add_option("-v", action="store_true", dest="vnc", help="open vnc display")
parser.add_option("-c", action="store", dest="host", help="host to be connected")
(options, args) = parser.parse_args()
if len(args) != 1:
parser.error("no xml_config")
try:
xml_config = open(args[0]).read()
except:
print "open or read %s failed." % (args[0])
sys.exit(1)
conn = libvirt.open(get_uri(options.host))
if conn == None:
print 'Failed to open connection to the hypervisor'
sys.exit(1)
try:
dom = conn.createXML(xml_config, 0)
except:
print "createXML failed"
sys.exit(1)
if options.vnc:
run_vncviewer(dom, options.host)
conn.close()
- 28 -
vdestroy
#!/usr/bin/python
import libvirt
import sys
import os
from optparse import OptionParser
from vfunctions import find_dom_by_name
usage = "usage: vdestroy [-c host] name"
parser = OptionParser(usage)
parser.add_option("-c", action="store", dest="host", help="host to be connected")
(options, args) = parser.parse_args()
if len(args) != 1:
parser.error("name not specified")
name = args[0]
dom, conn, h = find_dom_by_name(name, options.host)
if dom == None:
print "%s not found" % (name)
sys.exit(1)
try:
dom.destroy()
except:
print "destroy failed"
sys.exit(1)
conn.close()
- 29 -
vdetach
#!/usr/bin/python
import libvirt
import sys
import os
from optparse import OptionParser
from vfunctions import find_dom_by_name
usage = "usage: vdetach [-c host] name xml_config"
parser = OptionParser(usage)
parser.add_option("-c", action="store", dest="host", help="host to be connected")
(options, args) = parser.parse_args()
if len(args) != 2:
parser.error("no name or xml_config")
name = args[0]
try:
xml_config = open(args[1]).read()
except:
print "open or read %s failed." % (args[1])
sys.exit(1)
dom, conn, h = find_dom_by_name(name, options.host)
if dom == None:
print "%s not found" % (name)
sys.exit(1)
try:
dom.detachDevice(xml_config)
except:
print "detachDevice failed"
sys.exit(1)
conn.close()
- 30 -
functions.py
#!/usr/bin/python
import libvirt
import sys
import os
import libxml2
import commands
hypervisor = "qemu"
remote_protocol = "ssh"
local_uri = "system"
host_uri = [("localhost", "qemu:///system"),
("ipa2", "qemu+ssh://ipa2/system"),
("ipa3", "qemu+ssh://ipa3/system"),
("ipa4", "xen+ssh://ipa4/")]
def get_uri(host = None):
if host == None: host = "localhost"
for h, uri in host_uri:
if h == host: return uri
return "%s+%s://%s/%s" % (hypervisor, remote_protocol, host, local_uri)
def get_uri_all():
return host_uri
def get_interfaces(dom):
doc = libxml2.parseDoc(dom.XMLDesc(0))
context = doc.xpathNewContext()
nodes = context.xpathEval("/domain/devices/interface/target/@dev")
devs = []
for node in nodes:
dev = node.getContent()
devs.append(dev)
context.xpathFreeContext()
doc.freeDoc()
return devs
def get_disks(dom):
doc = libxml2.parseDoc(dom.XMLDesc(0))
context = doc.xpathNewContext()
nodes = context.xpathEval("/domain/devices/disk/target/@dev")
devs = []
for node in nodes:
dev = node.getContent()
devs.append(dev)
context.xpathFreeContext()
doc.freeDoc()
return devs
def get_vnc_port(dom):
doc = libxml2.parseDoc(dom.XMLDesc(0))
context = doc.xpathNewContext()
nodes = context.xpathEval("/domain/devices/graphics[@type='vnc']/@port")
if len(nodes) == 0: return None
port = nodes[0].getContent()
context.xpathFreeContext()
doc.freeDoc()
return port
def run_vncviewer(dom, host = None):
port = get_vnc_port(dom)
if port == None: return
if host == None or host == "localhost":
cmd = "vncviewer :" + port + " 2>/dev/null &"
else:
cmd = "vncviewer " + host + ":" + port + " 2>/dev/null &"
os.system(cmd)
def find_dom_by_name(name, host = None):
if host == None:
uris = get_uri_all()
else:
uris = [(host, get_uri(host))]
for h, uri in uris:
try:
conn = libvirt.open(uri)
except:
- 31 -
continue
ids = conn.listDomainsID()
if len(ids) == 0:
continue
for id in ids:
try:
dom = conn.lookupByID(id)
except:
continue
if dom.name() == name:
return (dom, conn, h)
conn.close()
return (None, None, None)
def get_ip_addr(dom):
doc = libxml2.parseDoc(dom.XMLDesc(0))
context = doc.xpathNewContext()
nodes = context.xpathEval("/domain/devices/interface/mac/@address")
if len(nodes) == 0: return None
mac_addr = nodes[0].getContent()
context.xpathFreeContext()
doc.freeDoc()
cmd = "grep %s /var/lib/misc/dnsmasq.leases" % mac_addr
ip_info = commands.getoutput(cmd)
if len(ip_info) != 0:
ip_addr = ip_info.split()[2]
return ip_addr
return None
- 32 -
vlist
#!/usr/bin/python
import libvirt
import sys
import os
from optparse import OptionParser
from xml.dom.minidom import parseString
from vfunctions import get_uri, get_uri_all, get_vnc_port, get_ip_addr
state_str = ["no-state", "running", "blocked", "paused", "in-shutdown", "shutdown", "crashed"]
usage = "usage: vlist [-c host | -a]"
parser = OptionParser(usage)
parser.add_option("-c", action="store", dest="host", help="host to be connected")
parser.add_option("-a", action="store_true", dest="all", help="list all hosts")
(options, args) = parser.parse_args()
if len(args) != 0:
parser.error("arg not need")
if options.host != None:
uris = [(options.host, get_uri(options.host))]
elif options.all:
uris = get_uri_all()
else:
uris = [("localhost", get_uri())]
for h, uri in uris:
conn = libvirt.openReadOnly(uri)
if conn == None:
print "Failed to open connection to the hypervisor"
sys.exit(1)
ids = conn.listDomainsID()
if ids == None:
print "ids None"
if len(ids) == 0:
print "%s: no VM found" % (h)
continue
for id in ids:
try:
dom = conn.lookupByID(id)
except:
print 'Failed to find the domain %d'
sys.exit(1)
state = state_str[dom.info()[0]]
port = get_vnc_port(dom)
if port == None: port = "-"
ip_addr = get_ip_addr(dom)
if ip_addr == None: ip_addr = "-"
print "%s: %d %s %s %s %s" % (h, id, dom.name(), state, port, ip_addr)
conn.close()
- 33 -
vmigrate
#!/usr/bin/python
import libvirt
import sys
import os
from optparse import OptionParser
from xml.dom.minidom import parseString
from vfunctions import get_uri, run_vncviewer, find_dom_by_name
usage = "usage: vmigrate [-v] [-l] [-c host] name dest"
parser = OptionParser(usage)
parser.add_option("-l", action="store_true", dest="live", help="live migration")
parser.add_option("-v", action="store_true", dest="vnc", help="open vnc display")
parser.add_option("-c", action="store", dest="host", help="src host to be connected")
(options, args) = parser.parse_args()
if len(args) != 2:
parser.error("no name or dest")
name = args[0]
dest = args[1]
dom, conn, h = find_dom_by_name(name, options.host)
if dom == None:
print "%s not found" % (name)
sys.exit(1)
dconn = libvirt.open(get_uri(dest))
if dconn == None:
print 'Failed to open connection to the hypervisor'
sys.exit(1)
flags = 0
if options.live:
flags = 1 # VIR_MIGRATE_LIVE
uri = None
bandwidth = 0
new_dom = dom.migrate(dconn, flags, name, uri, bandwidth)
if options.vnc:
run_vncviewer(new_dom, dest)
conn.close()
dconn.close()
- 34 -
vrestore
#!/usr/bin/python
import libvirt
import sys
import os
import os.path
from optparse import OptionParser
from vfunctions import get_uri, run_vncviewer
usage = "usage: vrestore [-v] [-c host] save_file"
parser = OptionParser(usage)
parser.add_option("-v", action="store_true", dest="vnc", help="open vnc display")
parser.add_option("-c", action="store", dest="host", help="host to be connected")
(options, args) = parser.parse_args()
if len(args) != 1:
parser.error("no save_file")
path = args[0]
conn = libvirt.open(get_uri(options.host))
if conn == None:
print "Failed to open connection to the hypervisor"
sys.exit(1)
try:
conn.restore(path)
except:
print "restore failed"
sys.exit(1)
name = os.path.basename(path)
try:
dom = conn.lookupByName(name)
except:
print "%s not found" % (name)
sys.exit(1)
if options.vnc:
run_vncviewer(dom, options.host)
conn.close()
- 35 -
vresume
#!/usr/bin/python
import libvirt
import sys
import os
from optparse import OptionParser
from vfunctions import find_dom_by_name
usage = "usage: vresume [-c host] name"
parser = OptionParser(usage)
parser.add_option("-c", action="store", dest="host", help="host to be connected")
(options, args) = parser.parse_args()
if len(args) != 1:
parser.error("name not specified")
name = args[0]
dom, conn, h = find_dom_by_name(name, options.host)
if dom == None:
print "%s not found" % (name)
sys.exit(1)
try:
dom.resume()
except:
print "resume failed"
sys.exit(1)
conn.close()
- 36 -
vsave
#!/usr/bin/python
import libvirt
import sys
import os
from optparse import OptionParser
from vfunctions import find_dom_by_name
usage = "usage: vsave [-c host] name save_file"
parser = OptionParser(usage)
parser.add_option("-c", action="store", dest="host", help="host to be connected")
(options, args) = parser.parse_args()
if len(args) != 2:
parser.error("number of argment incorrect")
name = args[0]
path = args[1]
dom, conn, h = find_dom_by_name(name, options.host)
if dom == None:
print "%s not found" % (name)
sys.exit(1)
try:
dom.save(path)
except:
print "save failed"
sys.exit(1)
print "%s is saved to %s" % (name, path)
conn.close()
- 37 -
vshutdown
#!/usr/bin/python
import libvirt
import sys
import os
from optparse import OptionParser
from vfunctions import find_dom_by_name
usage = "usage: vshutdown [-c host] name"
parser = OptionParser(usage)
parser.add_option("-c", action="store", dest="host", help="host to be connected")
(options, args) = parser.parse_args()
if len(args) != 1:
parser.error("name not specified")
name = args[0]
dom, conn, h = find_dom_by_name(name, options.host)
if dom == None:
print "%s not found" % (name)
sys.exit(1)
try:
dom.shutdown()
except:
print "shutdown failed"
sys.exit(1)
conn.close()
- 38 -
vstats
#!/usr/bin/python
import libvirt
import sys
import os
from optparse import OptionParser
from xml.dom.minidom import parseString
import commands
from vfunctions import find_dom_by_name, get_disks, get_interfaces
usage = "usage: vstats [-c host] name"
parser = OptionParser(usage)
parser.add_option("-c", action="store", dest="host", help="host to be connected")
(options, args) = parser.parse_args()
if len(args) != 1:
parser.error("no name")
name = args[0]
dom, conn, host = find_dom_by_name(name, options.host)
if dom == None:
print "%s not found" % (name)
sys.exit(1)
state, maxmem, mem, nvcpu, cputime = dom.info()
print
print
print
print
"max memory: %d MB" % (maxmem / 1024)
"current memory: %d MB" % (mem / 1024)
"num vcpu: %d" % (nvcpu)
"cpu usage: %d.%d sec" % (cputime / 1000000000, cputime % 1000000000)
devs = get_disks(dom)
for dev in devs:
rd_req, rd_bytes, wr_req, wr_bytes, err = dom.blockStats(dev)
print "%s: rd_req = %d, rd_bytes = %d, wr_req = %d, wr_bytes = %d" % (dev, rd_req, rd_bytes,
wr_req, wr_bytes)
devs = get_interfaces(dom)
for dev in devs:
rx_bytes, rx_packets, rx_errs, rx_drop, tx_bytes, tx_packets, tx_errs, tx_drop =
dom.interfaceStats(dev)
print "%s: rx_bytes = %d, rx_packets = %d, rx_errs = %d, rx_drop = %d, tx_bytes = %d,
tx_packets = %d, tx_errs = %d, tx_drop = %d" % (dev, rx_bytes,
rx_packets, rx_errs, rx_drop, tx_bytes, tx_packets, tx_errs, tx_drop)
conn.close()
- 39 -
vsuspend
#!/usr/bin/python
import libvirt
import sys
import os
from optparse import OptionParser
from vfunctions import find_dom_by_name
usage = "usage: vsuspend [-c host] name"
parser = OptionParser(usage)
parser.add_option("-c", action="store", dest="host", help="host to be connected")
(options, args) = parser.parse_args()
if len(args) != 1:
parser.error("name not specified")
name = args[0]
dom, conn, h = find_dom_by_name(name, options.host)
if dom == None:
print "%s not found" % (name)
sys.exit(1)
try:
dom.suspend()
except:
print "suspend failed"
sys.exit(1)
conn.close()
- 40 -