こんにちは、ADN事業部のt_oookaです。
前回は、virt-installコマンドで仮想マシンを作成し、virt-cloneコマンドにて 仮想マシンの複製を行う方法について記載しました。
今回は、複製する操作をもう少し効率化する方法について触れてみたいと 思います。
「libguestfs」を使用する
virt-cloneコマンドにより複製を実行する都度、複製を行った仮想マシンへ コンソール接続を行うのは、複製する仮想マシンが多くなるとちょっとした 作業になるので、この部分の効率化を行います。
「libguestfs」パッケージのインストール
[bash]# yum install libguestfs libguestfs-tools libguestfs-tools-c[/bash]
「virt-edit」で複製した仮想マシンの設定を直接変更する
最初に、前回と同様に「virt-clone」コマンドにより仮想マシンの複製を 行います。
複製元のゲストを「centos63」、複製するゲストを「guest02」とします。
[bash]# virt-clone --original centos63 --name guest02 --file /var/lib/libvirt/images/guest02 Allocating 'guest02' | 5.0 GB 00:26
Clone 'guest02' created successfully.[/bash]
※ この時点では、複製を行った「guest02」は起動させず、停止状態にしておきます。
[bash]# virsh list --all
Id Name State
- centos63 shut off
- guest01 shut off
- guest02 shut off[/bash]
「virt-clone」コマンド実行後、複製を行ったゲストに対して変更を行う ファイルは、今回の場合は以下の通りです。
- /etc/hosts
- /etc/sysconfig/network
- /etc/sysconfig/network-scripts/ifcfg-eth0
- /etc/udev/rules.d/70-persistent-net.rules
前回は、複製を行ったゲストを起動し、コンソール接続を行い 上記の設定ファイルの変更を行いました。 今回は、ホスト側から複製を行ったゲストの設定を直接変更を 行うため、複製を行ったゲストの起動及びゲストへのコンソール 接続は行いません。
ホスト名の変更
まずは、複製を行ったゲスト(guest02)の/etc/hostsを編集します。
[bash]# virt-edit -d guest02 /etc/hosts[/bash]
「d」オプションで対象のゲストを指定し、続く引数で編集を行うファイルのパスを 指定します。
・編集前
127.0.0.1 centos63.example.com localhost localhost.localdomain localhost4 localhost4.localdomain4 ::1 centos63.example.com localhost localhost.localdomain localhost6 localhost6.localdomain6
・編集後
127.0.0.1 guest02.example.com localhost localhost.localdomain localhost4 localhost4.localdomain4 ::1 guest02.example.com localhost localhost.localdomain localhost6 localhost6.localdomain6
編集を保存後、一応編集後のファイルの内容を確認しておきます。 「virt-cat」コマンドを使用します。
[bash]# virt-cat -d guest02 /etc/hosts[/bash]
※ 上記の「編集後」の内容が表示されることを確認します。
続いて、/etc/sysconfig/networkを編集します。
[bash]# virt-edit -d guest02 /etc/sysconfig/network[/bash]
・編集前
NETWORKING=yes HOSTNAME=centos63.example.com
・編集後
NETWORKING=yes
HOSTNAME=guest02.example.com
ネットワーク設定の変更
ホスト名の変更と同様に「virt-edit」コマンドを使用してファイルの編集を行えばよいのですが、 ネットワーク設定の場合は、複製を行ったゲストのインタフェースのMACアドレスを事前に確認 しておく必要があります。 ※ virt-cloneコマンドにてMACアドレスを指定した場合は不要です。
[bash]# virsh domiflist guest02
Interface Type Source Model MAC
- bridge virbr0 virtio '52:54:00:ca:17:e2'[/bash]
MAC欄に表示された値が複製を行ったゲスト(guest02)のインタフェースのMACアドレスと なります。
一応、複製元のMACアドレスも確認しておきます。
[bash]# virsh domiflist centos63
Interface Type Source Model MAC
- bridge virbr0 virtio '52:54:00:3e:43:37'[/bash]
また、uuidもあらかじめ「uuidgen」コマンドで準備しておきます。
[bash]# uuidgen b6c7e5d8-a3f1-4d8d-b7b9-1daddfe4ba80[/bash]
MACアドレスの確認及びuuidの準備が行えたため、複製を行ったゲスト(guest02)の ネットワーク設定を変更していきます。
[bash]# virt-edit -d guest02 /etc/sysconfig/network-scripts/ifcfg-eth0[/bash]
・編集前
DEVICE="eth0" BOOTPROTO="static" HWADDR="52:54:00:3E:43:37" NM_CONTROLLED="no" ONBOOT="yes" TYPE="Ethernet" UUID="35000132-d23b-48fe-a06e-59ba9b692690" IPADDR=192.168.122.2 NETMASK=255.255.255.0
・編集後
DEVICE="eth0" BOOTPROTO="static" HWADDR="52:54:00:ca:17:e2" NM_CONTROLLED="no" ONBOOT="yes" TYPE="Ethernet" UUID="b6c7e5d8-a3f1-4d8d-b7b9-1daddfe4ba80" IPADDR=192.168.122.3 NETMASK=255.255.255.0
HWADDRを上記で確認したMACアドレスへ変更します。 また、UUIDも上記で生成したuuidに変更します。 IPアドレスとして「192.168.122.3」をアサインします。
同様に/etc/udev/rules.d/70-persistent-net.rulesも編集します。
[bash]# virt-edit -d guest02 /etc/udev/rules.d/70-persistent-net.rules[/bash]
・編集前
# This file was automatically generated by the /lib/udev/write_net_rules # program, run by the persistent-net-generator.rules rules file. # # You can modify it, as long as you keep each rule on a single # line, and change only the value of the NAME= key. # PCI device 0x1af4:0x1000 (virtio-pci) SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="52:54:00:3e:43:37", ATTR{type}=="1", KERNEL=="eth*", NAME="eth0"
・編集後
# This file was automatically generated by the /lib/udev/write_net_rules # program, run by the persistent-net-generator.rules rules file. # # You can modify it, as long as you keep each rule on a single # line, and change only the value of the NAME= key. # PCI device 0x1af4:0x1000 (virtio-pci) SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="52:54:00:ca:17:e2", ATTR{type}=="1", KERNEL=="eth*", NAME="eth0"
ATTR{address}==""を上記で確認したMACアドレスへ変更します。
複製したゲストの動作確認
複製したゲスト(guest02)を起動します。
[bash]# virsh start guest02[/bash]
複製したゲストの状態を確認します。
[bash]# virsh list --all
Id Name State
47 guest_02 running - centos63 shut off - guest01 shut off[/bash]
複製したゲスト(guest02)へコンソール接続します。
[bash]# virsh console guest02 Connected to domain guest02 Escape character is ^]
CentOS release 6.3 (Final) Kernel 2.6.32-279.19.1.el6.x86_64 on an x86_64
guest02.example.com login:[/bash]
※ 以降は、ゲストでの操作となります。
ホスト名の確認 [bash]# hostname guest02.example.com[/bash]
ネットワーク設定の確認 [bash]# ifconfig[/bash]
スクリプトによる仮想マシン複製の自動化
上記までで、複製の操作自体はホスト側で行えるように なりました。
ゲスト側での操作がなくなり、ある程度効率化できたように 思います。
とはいえ、やはり最終的にはスクリプトで。。。 ということで、自動化してみます。
コピー元は、テンプレート用途の「centos63」とします。 前回、IPアドレスとして「192.168.122.2」をアサインして いますので、その前提でスクリプトを作成しています。
・clone-guest.sh
[bash]
!/bin/sh
work_dir=/tmp/clone-guest
cmd_awk=/bin/awk cmd_cat=/bin/cat cmd_cut=/bin/cut cmd_grep=/bin/grep cmd_mkdir=/bin/mkdir cmd_sed=/bin/sed cmd_uuidgen=/usr/bin/uuidgen cmd_virsh=/usr/bin/virsh cmd_virt_cat=/usr/bin/virt-cat cmd_virt_clone=/usr/bin/virt-clone cmd_virt_copy_in=/usr/bin/virt-copy-in
original_domain_name=centos63 original_fqdn=${original_domain_name}.example.com original_ipaddr=192.168.122.2 source_bridge=virbr0 clone_domain_name=$1 clone_fqdn=${clone_domain_name}.example.com clone_ipaddr=$2
domain_image_dir=/var/lib/libvirt/images clone_domain_image_path=$domain_image_dir/$clone_domain_name
--------------------------------------------------
pre process.
--------------------------------------------------
if [ "$clone_domain_name" = "" -o "$clone_ipaddr" = "" ] ; then echo "Usage clone-guest.sh <domain_name> <ipaddr>" exit 0 fi
[ ! -e $work_dir ] && $cmd_mkdir -p $work_dir
--------------------------------------------------
main process.
--------------------------------------------------
$cmd_virt_clone \ --original $original_domain_name \ --name $clone_domain_name \ --file $clone_domain_image_path
----- /etc/hosts -----
$cmd_virt_cat -d $original_domain_name /etc/hosts \ > $work_dir/hosts.org $cmd_cat $work_dir/hosts.org \ | $cmd_sed "s/$original_fqdn/$clone_fqdn/" \ > $work_dir/hosts $cmd_virt_copy_in -d $clone_domain_name $work_dir/hosts /etc/
----- /etc/sysconfig/network ------
$cmd_virt_cat -d $original_domain_name /etc/sysconfig/network \ > $work_dir/network.org $cmd_cat $work_dir/network.org \ | $cmd_sed "s/$original_fqdn/$clone_fqdn/" \ > $work_dir/network
----- /etc/sysconfig/network-scripts/ifcfg-eth0 ------
original_mac_addr=$( \ $cmd_virsh domiflist $original_domain_name \ | $cmd_grep $source_bridge \ | $cmd_awk '{print $5}' \ ) clone_mac_addr=$( \ $cmd_virsh domiflist $clone_domain_name \ | $cmd_grep $source_bridge \ | $cmd_awk '{print $5}' \ )
original_nic_uuid=$( \ $cmd_cat $work_dir/ifcfg-eth0.org \ | $cmd_grep -i uuid \ | $cmd_cut -d'=' -f2 \ | $cmd_sed 's/"//g' \ ) clone_nic_uuid=$($cmd_uuidgen)
$cmd_virt_cat -d $original_domain_name \ /etc/sysconfig/network-scripts/ifcfg-eth0 \ > $work_dir/ifcfg-eth0.org $cmd_cat $work_dir/ifcfg-eth0.org \ | $cmd_sed -e "s/$original_mac_addr/$clone_mac_addr/i" \ -e "s/$original_nic_uuid/$clone_nic_uuid/i" \ -e "s/$original_ipaddr/$clone_ipaddr/i" \ > $work_dir/ifcfg-eth0 $cmd_virt_copy_in -d $clone_domain_name \ $work_dir/ifcfg-eth0 \ /etc/sysconfig/network-scripts/
----- /etc/udev/rules.d/70-persistent-net.rules -----
$cmd_virt_cat -d $original_domain_name \ /etc/udev/rules.d/70-persistent-net.rules \ > $work_dir/70-persistent-net.rules.org $cmd_cat $work_dir/70-persistent-net.rules.org \ | $cmd_sed "s/$original_mac_addr/$clone_mac_addr/i" \ > $work_dir/70-persistent-net.rules $cmd_virt_copy_in -d $clone_domain_name \ $work_dir/70-persistent-net.rules \ /etc/udev/rules.d/[/bash]
使用方法は、以下の通りです。 [bash]# /bin/sh clone-guest.sh <domain_name> <ipaddr>[/bash]
ドメイン名「guest03」とし、IPアドレス「192.168.122.4」をアサインする場合は、 [bash]# /bin/sh clone-guest.sh guest03 192.168.122.4[/bash]
となります。
「libguestfs」には、今回触れた以外にもコマンドが含まれていますので、 関心のある方はその他のコマンドにも触れてみてください。
上記のスクリプトではかなり制限があるのも事実ですので、より多くのケースに 対応できる自動化のスクリプトを作成することができると思います。