Created
April 29, 2011 09:50
-
-
Save manabu/948124 to your computer and use it in GitHub Desktop.
kvmclone for ubuntu
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/perl | |
# | |
# kvmclone.pl for ubuntu | |
# | |
# 2009/12/22 ver1.0 | |
# 2011/02/02 ver1.1 add LANG=C | |
# 2011/04/23 ver1.2 support for RHEL6.0 | |
# | |
# 2011/04/29 support for ubuntu | |
# | |
# test only 11.04. | |
# when you want to clone qcow2 image, you need "qemu-nbd". | |
# | |
use strict; | |
use vars qw( $opt_t $opt_o $opt_n $opt_i $opt_m $opt_g $opt_s $opt_h $opt_a ); | |
use Getopt::Std; | |
$ENV{'LANG'} = "C"; | |
sub chkopts { | |
getopts( 'ahs:t:o:n:i:k:g:b:c:m:' ); | |
$opt_h = 1 unless ( $opt_t && $opt_o && $opt_n && $opt_i && $opt_m && | |
$opt_g && $opt_s ); | |
if ( $opt_h ) { | |
print <<EOF; | |
usage: kvmclone.pl [-aontsimg] | |
-a: Activate vm after cloning | |
-o: Original domain name | |
-n: New domain name | |
-t: Target disk image file | |
-s: Server hostname | |
-i: IP Address | |
-m: Net mask | |
-g: Default gateway | |
EOF | |
exit 0; | |
} | |
$opt_t = "/var/lib/libvirt/images/" . $opt_t unless ( $opt_t =~ m/^\// ); | |
} | |
sub log_cmd { | |
print "===> Exec: $_[ 0 ]\n"; | |
system ( $_[ 0 ] ); | |
} | |
sub chkvm { | |
if ( system( "virsh dominfo $opt_o | grep -E \"^State: +shut off\$\" >/dev/null 2>&1" ) ) { | |
print "Domain $opt_o is running, shutdown first.\n\n"; | |
exit 1; | |
} | |
} | |
sub clonfiles { | |
my ( $old_mac, $mac, $loopdev, $s ); | |
my @dpart; | |
my $tmpmnt = "/tmp/tmpmnt$$"; | |
print( "\nCloning disk image file of $opt_o to $opt_t...\n" ); | |
log_cmd( "virt-clone --prompt --original $opt_o --name $opt_n --file $opt_t --nonsparse" ); | |
$_ = `grep \"mac address\" /etc/libvirt/qemu/${opt_o}.xml`; | |
$_ =~ m/address=\'(\w\w:\w\w:\w\w:\w\w:\w\w:\w\w)\'/; $old_mac = $1; | |
$_ = `grep \"mac address\" /etc/libvirt/qemu/${opt_n}.xml`; | |
$_ =~ m/address=\'(\w\w:\w\w:\w\w:\w\w:\w\w:\w\w)\'/; $mac = $1; | |
print "\nModifying network information in the new disk image...\n\n"; | |
my $qcow2; | |
my $filetype = `file $opt_t`; | |
if( $filetype =~ /QEMU QCOW Image \(v2\)/ ){ | |
$qcow2 = 1; | |
print "$opt_t is qcow2\n"; | |
}else{ | |
$qcow2 = 0; | |
print "$opt_t is raw\n"; | |
} | |
print "Now trying to find root partition...\n"; | |
if($qcow2){ | |
print "qcow2 mount takes 5sec sleep for safety\n"; | |
sleep(5); | |
$loopdev = "/dev/nbd0"; | |
log_cmd ( "qemu-nbd -c $loopdev $opt_t" ); | |
print "qcow2 mount takes more 5sec sleep for safety.(this is last sleep).\n"; | |
sleep(5); | |
print "qcow2 sleep end\n"; | |
}else{ | |
$loopdev = `losetup -f`; chomp $loopdev; | |
log_cmd ( "losetup $loopdev $opt_t" ); | |
} | |
$s = `kpartx -av $loopdev`; @dpart = split( /\n/, $s ); | |
log_cmd ( "mkdir -p $tmpmnt" ); | |
foreach $s ( @dpart ) { | |
$s = $1 if ( $s =~ m/add map (\w+) / ); | |
log_cmd ( "mount /dev/mapper/$s $tmpmnt" ); | |
if ( -d "$tmpmnt/etc/network" ) { | |
print "\nFound root partition on $s\n"; | |
goto OUT; | |
} else { | |
log_cmd ( "umount $tmpmnt" ); | |
} | |
} | |
print "Failed to find root partition.\n"; | |
if($qcow2){ | |
log_cmd ( "kpartx -d $loopdev; qemu-nbd -d $loopdev; rmdir $tmpmnt" ); | |
}else{ | |
log_cmd ( "kpartx -d $loopdev; losetup -d $loopdev; rmdir $tmpmnt" ); | |
} | |
exit 1; | |
OUT: | |
if ( -f "$tmpmnt/etc/udev/rules.d/70-persistent-net.rules" ) { | |
open ( IN, "<$tmpmnt/etc/udev/rules.d/70-persistent-net.rules" ); | |
open ( OUT, ">$tmpmnt/etc/udev/rules.d/70-persistent-net.rules_new" ); | |
while (<IN>) { | |
$_ =~ s/\r\n$/\n/; | |
$_ =~ s/==\"$old_mac\"/==\"$mac\"/; | |
print OUT $_; | |
} | |
close OUT; | |
close IN; | |
log_cmd ( "mv -f $tmpmnt/etc/udev/rules.d/70-persistent-net.rules_new $tmpmnt/etc/udev/rules.d/70-persistent-net.rules" ); | |
print "\nNew mac address in udev file....\n"; | |
print "---------------------------\n"; | |
system ( "grep \"address\" $tmpmnt/etc/udev/rules.d/70-persistent-net.rules" ); | |
print "---------------------------\n"; | |
} | |
open ( OUT, ">$tmpmnt/etc/hostname" ); | |
print OUT $opt_s; | |
close OUT; | |
print "\nNew hostname config file....\n"; | |
print "---------------------------\n"; | |
system ( "cat $tmpmnt/etc/hostname" ); | |
print "---------------------------\n"; | |
open ( IN, "<$tmpmnt/etc/network/interfaces" ); | |
open ( OUT, ">$tmpmnt/etc/network/interfaces_new" ); | |
while (<IN>) { | |
$_ =~ s/\r\n$/\n/; | |
$_ =~ s/$old_mac/$mac/; | |
$_ =~ s/\s*address\s*[\"\d\.]+/address $opt_i/i; | |
$_ =~ s/\s*netmask\s*[\"\d\.]+/netmask $opt_m/i; | |
$_ =~ s/\s*gateway\s*[\"\d\.]+/gateway $opt_g/i; | |
print OUT $_; | |
} | |
close OUT; | |
close IN; | |
log_cmd ( "mv -f $tmpmnt/etc/network/interfaces_new $tmpmnt/etc/network/interfaces" ); | |
print "\nNew interface eth0 config file....\n"; | |
print "---------------------------\n"; | |
system ( "cat $tmpmnt/etc/network/interfaces" ); | |
print "---------------------------\n"; | |
log_cmd ( "umount $tmpmnt" ); | |
if($qcow2){ | |
log_cmd ( "kpartx -d $loopdev; qemu-nbd -d $loopdev; rmdir $tmpmnt" ); | |
}else{ | |
log_cmd ( "kpartx -d $loopdev; losetup -d $loopdev; rmdir $tmpmnt" ); | |
} | |
exit 1; | |
} | |
MAIN: { | |
chkopts(); | |
chkvm(); | |
clonfiles(); | |
if ( $opt_a ) { | |
print "\nActivate new vm $opt_n\n"; | |
log_cmd ( "virsh start $opt_n" ); | |
} | |
print "Done.\n"; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment