@ -4,7 +4,7 @@
# Daniel Berteaud <daniel@firewall-services.com>
# Daniel Berteaud <daniel@firewall-services.com>
#
#
# COPYRIGHT
# COPYRIGHT
# Copyright (C) 2009-2015 Daniel Berteaud
# Copyright (C) 2009-2018 Daniel Berteaud
#
#
# This program is free software; you can redistribute it and/or modify
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# it under the terms of the GNU General Public License as published by
@ -44,6 +44,8 @@ our @disks = ();
$opts{action} = 'dump';
$opts{action} = 'dump';
# Where backups will be stored. This directory must already exists
# Where backups will be stored. This directory must already exists
$opts{backupdir} = '/var/lib/libvirt/backup';
$opts{backupdir} = '/var/lib/libvirt/backup';
# dump cmd can be used to pipe the data to a custom commands, instead of storing it in backupdir
$opts{dumpcmd} = undef;
# Lockdir is where locks will be held when backing up a VM. The default is to put the lock
# Lockdir is where locks will be held when backing up a VM. The default is to put the lock
# in the backup dir of the VM, but in some situations, you want to put it elsewhere
# in the backup dir of the VM, but in some situations, you want to put it elsewhere
$opts{lockdir} = '';
$opts{lockdir} = '';
@ -107,6 +109,7 @@ GetOptions(
"state" => \$opts{state},
"state" => \$opts{state},
"snapsize=s" => \$opts{snapsize},
"snapsize=s" => \$opts{snapsize},
"backupdir=s" => \$opts{backupdir},
"backupdir=s" => \$opts{backupdir},
"dumpcmd=s" => \$opts{dumpcmd},
"lockdir=s" => \$opts{lockdir},
"lockdir=s" => \$opts{lockdir},
"lvm=s" => \$opts{lvm},
"lvm=s" => \$opts{lvm},
"vm=s" => \@vms,
"vm=s" => \@vms,
@ -180,6 +183,11 @@ if ((!@vms) || ($opts{help})){
usage();
usage();
exit 1;
exit 1;
}
}
# dumpcmd can only be used with the dump action
if ($opts{dumpcmd} && $opt{action} != 'dump'){
usage();
exit 1;
}
# Or state and shutdown flags are used together
# Or state and shutdown flags are used together
if (($opts{state}) && ($opts{shutdown})){
if (($opts{state}) && ($opts{shutdown})){
print "State and shutdown flags cannot be used together\n";
print "State and shutdown flags cannot be used together\n";
@ -464,8 +472,13 @@ sub prepare_backup{
if ($opts{action} eq 'dump'){
if ($opts{action} eq 'dump'){
print "\n\nThe following disks will be dumped:\n\n";
print "\n\nThe following disks will be dumped:\n\n";
foreach $disk (@disks){
foreach $disk (@disks){
print "Source: $disk->{source}\tDest: $backupdir/$vm" . '_' . $disk->{target} .
if ($opts{dumpcmd}){
".img$opts{compext}\n";
print "Source: $disk->{source}\tBackup command: $opts{dumpcmd}\n";
}
else {
print "Source: $disk->{source}\tDest: $backupdir/$vm" . '_' . $disk->{target} .
".img$opts{compext}\n";
}
}
}
}
}
elsif ($opts{action} eq 'convert'){
elsif ($opts{action} eq 'convert'){
@ -530,8 +543,18 @@ sub run_dump{
if ($opts{debug} && $opts{compress} ne 'none')
if ($opts{debug} && $opts{compress} ne 'none')
}
}
else {
else {
print "\nStarting dump of $source to $dest\n\n" if ($opts{debug});
if ($opts{dumpcmd}){
$cmd = "$opts{ionice} dd if=$source bs=$opts{blocksize} | $opts{nice} $opts{compcmd} > $dest 2>/dev/null";
my $dumpcmd = $opts{dumpcmd};
$dumpcmd =~ s/{{VIRT_BACKUP_VM}}/$vm/g;
$dumpcmd =~ s/{{VIRT_BACKUP_DISK}}/$disk->{target}/g;
print "\nStarting dump of $source to command: $dumpcmd\n\n" if ($opts{debug});
$cmd = "$opts{ionice} dd if=$source bs=$opts{blocksize} 2>/dev/null | $opts{nice} $opts{compcmd}";
$cmd .= " | $dumpcmd 2>/dev/null";
}
else {
print "\nStarting dump of $source to $dest\n\n" if ($opts{debug});
$cmd = "$opts{ionice} dd if=$source bs=$opts{blocksize} | $opts{nice} $opts{compcmd} > $dest 2>/dev/null";
}
}
}
unless( system("$cmd") == 0 ){
unless( system("$cmd") == 0 ){
die "Couldn't dump or convert $source to $dest\n";
die "Couldn't dump or convert $source to $dest\n";
@ -661,7 +684,7 @@ sub run_cleanup{
sub usage{
sub usage{
print "usage:\n$0 --action=[dump|cleanup|chunkmount|unlock] --vm=vm1[,vm2,vm3] [--debug] [--exclude=hda,hdb] [--compress] ".
print "usage:\n$0 --action=[dump|cleanup|chunkmount|unlock] --vm=vm1[,vm2,vm3] [--debug] [--exclude=hda,hdb] [--compress] ".
"[--state] [--shutdown] [--shutdown-timeout] [--no-offline] [--no-snapshot] [--snapsize=<size>] [--backupdir=/path/to/dir] [--connect=<URI>] ".
"[--state] [--shutdown] [--shutdown-timeout] [--no-offline] [--no-snapshot] [--snapsize=<size>] [--backupdir=/path/to/dir] [--connect=<URI>] ".
"[--keep-lock] [--blocksize=<block size>]\n" .
"[--keep-lock] [--blocksize=<block size>] [--dumpcmd=<command>] \n" .
"\n\n" .
"\n\n" .
"\t--action: What action the script will run. Valid actions are\n\n" .
"\t--action: What action the script will run. Valid actions are\n\n" .
"\t\t- dump: Run the dump routine (dump disk image to temp dir, pausing the VM if needed). It's the default action\n" .
"\t\t- dump: Run the dump routine (dump disk image to temp dir, pausing the VM if needed). It's the default action\n" .
@ -699,6 +722,10 @@ sub usage{
"disk of a VM, but not the data one which can be backed up separatly, at the files level.\n\n" .
"disk of a VM, but not the data one which can be backed up separatly, at the files level.\n\n" .
"\t--backupdir=/path/to/backup: Use an alternate backup dir. The directory must exists and be writable. " .
"\t--backupdir=/path/to/backup: Use an alternate backup dir. The directory must exists and be writable. " .
"The default is /var/lib/libvirt/backup\n\n" .
"The default is /var/lib/libvirt/backup\n\n" .
"\t--dumpcmd=<command>: Do not store backup on disk, but redirect the output to a custom command instead. " .
"This lets you use your favorite backup script/software accepting backup data on STDIN. The variables " .
"{{VIRT_BACKUP_VM}} and {{VIRT_BACKUP_DISK}} will be substituted by the names of the current vm and disk. " .
"Disabled by default. Only valid if action is dump\n\n" .
"\t--lockdir=/path/to/locks: Use an alternate lock dir. The directory must exists and be writable. " .
"\t--lockdir=/path/to/locks: Use an alternate lock dir. The directory must exists and be writable. " .
"The default is to put locks in the backup diretory, but you might want it elsewhere (on a shared storage for example)\n\n" .
"The default is to put locks in the backup diretory, but you might want it elsewhere (on a shared storage for example)\n\n" .
"\t--connect=<URI>: URI to connect to libvirt daemon (to suspend, resume, save, restore VM etc...). " .
"\t--connect=<URI>: URI to connect to libvirt daemon (to suspend, resume, save, restore VM etc...). " .