FLINTERS Engineer's Blog

FLINTERSのエンジニアによる技術ブログ

KVMのCloneを作る時に面倒だったことを自動化してみる

みなさまこんばんわ。さげはしです。

最近は仮想化といえばvagrantが大いに盛り上がっておりますが、私は慣れ親しんだKVMが大好きです。vagrantも試そうと思ったけど、CUIしかないサーバでVirtualbox入れる自体があんまり情報ないし、KVMの性能は十分イイし…ということで、個人的にはまだまだKVM推しです。ローカルにはVagrantイイですけど。


ということで、KVMはベースを作っておいてvirt-cloneするのが一般的だと勝手に思ってますが、cloneするとxmlファイルのIDとかmacアドレスを良い感じに生成してくれますが、そのままサーバ(あ、うちはCentOSです)を起動すると、ifcfg-eth0のMACアドレスとランダム生成されたMACアドレスが違うもんで、色々と面倒になっちゃいますよね。

そこで、まぁ仮想化ファイルもqcow2じゃなくてraw限定で、ethも複数対応してないとかクソ仕様なのですが、現場困っていないので以下のスクリプトを晒してみます。

これを実行すると、Clone→rawイメージマウント→ifcfg-eth0のmacアドレス書き換え→umountまでやってくれます。
勉強のためにrubyで書いてみたけど自分のクソ能力に脱帽するしかない…。もっとrubyの勉強しよう。
そして次はChefをやるぞ!

#!/bin/env ruby

require 'rexml/document'

if ARGV[0].nil? then
  p "Error!"
  exit
end

name = ARGV[0]
base = 'base'
disk_image = "/var/kvm/images/#{name}.img"
mount_path = "/var/kvm/tmp"
edit_eth_file = "#{mount_path}/etc/sysconfig/network-scripts/ifcfg-eth0"

# clone kvm images.
puts "---- clone image data ----"
system("virt-clone --original #{base} --name #{name} --file #{disk_image}")

# get new mac address.
puts "---- get new mac address ----"
doc = REXML::Document.new(open("/etc/libvirt/qemu/#{name}.xml"))
macaddr = doc.elements[('domain/devices/interface/mac')].attributes['address']

# mount kvm raw images.
puts "---- mount image data ----"
system("losetup -f ")
system("losetup /dev/loop0 #{disk_image}")
system("kpartx -av /dev/loop0 && mount -t ext4 /dev/mapper/loop0p3 #{mount_path}")

# edit eth file.
puts "---- edit eth0 file ----"
out = ""
open(edit_eth_file) { |f|
  f.each { |line|
    if /^HWADDR/ =~ line
      out << "HWADDR=\"#{macaddr}\"\n"
    else
      out << line
    end
  }
}
fo = open(edit_eth_file, "w")
fo.puts out
fo.close

# umount images.
puts "---- umount image data ----"
system("umount #{mount_path}")
system("kpartx -dv /dev/loop0 && losetup -d /dev/loop0")

puts "---- Finish!! ----"

exit