2011-08-23 07:47:04 +02:00
package PVE::VZDump::QemuServer ;
use strict ;
use warnings ;
use File::Path ;
use File::Basename ;
2011-10-14 11:05:06 +02:00
use PVE::INotify ;
2011-08-23 07:47:04 +02:00
use PVE::VZDump ;
2012-12-12 15:35:26 +01:00
use PVE::IPCC ;
2011-10-17 13:49:48 +02:00
use PVE::Cluster qw( cfs_read_file ) ;
use PVE::Tools ;
2012-05-24 07:22:41 +02:00
use PVE::Storage::Plugin ;
2011-08-23 07:47:04 +02:00
use PVE::Storage ;
use PVE::QemuServer ;
use IO::File ;
2012-12-12 15:35:26 +01:00
use IPC::Open3 ;
2011-08-23 07:47:04 +02:00
use base qw ( PVE::VZDump:: Plugin ) ;
sub new {
my ( $ class , $ vzdump ) = @ _ ;
2014-12-10 06:40:21 +01:00
2011-10-14 11:05:06 +02:00
PVE::VZDump:: check_bin ( 'qm' ) ;
2011-08-23 07:47:04 +02:00
my $ self = bless { vzdump = > $ vzdump } ;
$ self - > { vmlist } = PVE::QemuServer:: vzlist ( ) ;
$ self - > { storecfg } = PVE::Storage:: config ( ) ;
return $ self ;
} ;
sub type {
return 'qemu' ;
}
sub vmlist {
my ( $ self ) = @ _ ;
return [ keys % { $ self - > { vmlist } } ] ;
}
sub prepare {
my ( $ self , $ task , $ vmid , $ mode ) = @ _ ;
$ task - > { disks } = [] ;
2016-03-07 12:41:12 +01:00
my $ conf = $ self - > { vmlist } - > { $ vmid } = PVE::QemuConfig - > load_config ( $ vmid ) ;
2011-08-23 07:47:04 +02:00
2012-12-12 15:35:26 +01:00
$ self - > { vm_was_running } = 1 ;
if ( ! PVE::QemuServer:: check_running ( $ vmid ) ) {
$ self - > { vm_was_running } = 0 ;
2012-09-27 09:42:48 +02:00
}
2011-08-23 07:47:04 +02:00
$ task - > { hostname } = $ conf - > { name } ;
2014-12-10 06:40:21 +01:00
my $ hostname = PVE::INotify:: nodename ( ) ;
2011-08-23 07:47:04 +02:00
2012-02-24 07:40:12 +01:00
my $ vollist = [] ;
my $ drivehash = { } ;
2011-08-23 07:47:04 +02:00
PVE::QemuServer:: foreach_drive ( $ conf , sub {
my ( $ ds , $ drive ) = @ _ ;
2012-05-24 07:22:41 +02:00
return if PVE::QemuServer:: drive_is_cdrom ( $ drive ) ;
2011-08-23 07:47:04 +02:00
2016-01-29 08:47:21 +01:00
if ( defined ( $ drive - > { backup } ) && ! $ drive - > { backup } ) {
2011-08-23 07:47:04 +02:00
$ self - > loginfo ( "exclude disk '$ds' (backup=no)" ) ;
return ;
2016-01-29 08:47:21 +01:00
} elsif ( $ drive - > { iothread } ) {
2015-07-21 15:14:36 +02:00
die "disk '$ds' (iothread=on) can't use backup feature currently. Please set backup=no for this drive" ;
2014-12-10 06:40:21 +01:00
}
2012-02-24 07:40:12 +01:00
my $ volid = $ drive - > { file } ;
2012-05-24 07:22:41 +02:00
my ( $ storeid , $ volname ) = PVE::Storage:: parse_volume_id ( $ volid , 1 ) ;
2012-02-24 07:40:12 +01:00
push @$ vollist , $ volid if $ storeid ;
$ drivehash - > { $ ds } = $ drive ;
} ) ;
PVE::Storage:: activate_volumes ( $ self - > { storecfg } , $ vollist ) ;
2012-11-05 06:26:25 +01:00
foreach my $ ds ( sort keys %$ drivehash ) {
my $ drive = $ drivehash - > { $ ds } ;
2014-12-10 06:40:21 +01:00
2011-08-23 07:47:04 +02:00
my $ volid = $ drive - > { file } ;
my $ path ;
2012-05-24 07:22:41 +02:00
my ( $ storeid , $ volname ) = PVE::Storage:: parse_volume_id ( $ volid , 1 ) ;
2011-08-23 07:47:04 +02:00
if ( $ storeid ) {
2012-02-24 07:40:12 +01:00
$ path = PVE::Storage:: path ( $ self - > { storecfg } , $ volid ) ;
2011-08-23 07:47:04 +02:00
} else {
$ path = $ volid ;
}
2012-02-24 07:40:12 +01:00
next if ! $ path ;
2011-08-23 07:47:04 +02:00
2013-02-17 11:01:39 +01:00
my $ format = undef ;
my $ size = undef ;
2011-08-23 07:47:04 +02:00
2013-02-17 11:01:39 +01:00
eval {
( $ size , $ format ) = PVE::Storage:: volume_size_info ( $ self - > { storecfg } , $ volid , 5 ) ;
} ;
die "no such volume '$volid'\n" if $@ ;
2012-12-12 15:35:26 +01:00
2014-12-10 06:40:21 +01:00
my $ diskinfo = { path = > $ path , volid = > $ volid , storeid = > $ storeid ,
2012-12-12 15:35:26 +01:00
format = > $ format , virtdev = > $ ds , qmdevice = > "drive-$ds" } ;
2011-08-23 07:47:04 +02:00
if ( - b $ path ) {
$ diskinfo - > { type } = 'block' ;
} else {
$ diskinfo - > { type } = 'file' ;
}
push @ { $ task - > { disks } } , $ diskinfo ;
2012-02-24 07:40:12 +01:00
}
2011-08-23 07:47:04 +02:00
}
sub vm_status {
my ( $ self , $ vmid ) = @ _ ;
2011-10-14 11:05:06 +02:00
my $ running = PVE::QemuServer:: check_running ( $ vmid ) ? 1 : 0 ;
2014-12-10 06:40:21 +01:00
return wantarray ? ( $ running , $ running ? 'running' : 'stopped' ) : $ running ;
2011-08-23 07:47:04 +02:00
}
sub lock_vm {
my ( $ self , $ vmid ) = @ _ ;
$ self - > cmd ( "qm set $vmid --lock backup" ) ;
}
sub unlock_vm {
my ( $ self , $ vmid ) = @ _ ;
2011-10-14 11:05:06 +02:00
$ self - > cmd ( "qm unlock $vmid" ) ;
2011-08-23 07:47:04 +02:00
}
sub stop_vm {
my ( $ self , $ task , $ vmid ) = @ _ ;
my $ opts = $ self - > { vzdump } - > { opts } ;
my $ wait = $ opts - > { stopwait } * 60 ;
# send shutdown and wait
2012-01-17 11:56:56 +01:00
$ self - > cmd ( "qm shutdown $vmid --skiplock --keepActive --timeout $wait" ) ;
2011-08-23 07:47:04 +02:00
}
sub start_vm {
my ( $ self , $ task , $ vmid ) = @ _ ;
2011-10-14 11:05:06 +02:00
$ self - > cmd ( "qm start $vmid --skiplock" ) ;
2011-08-23 07:47:04 +02:00
}
sub suspend_vm {
my ( $ self , $ task , $ vmid ) = @ _ ;
2011-10-14 11:05:06 +02:00
$ self - > cmd ( "qm suspend $vmid --skiplock" ) ;
2011-08-23 07:47:04 +02:00
}
sub resume_vm {
my ( $ self , $ task , $ vmid ) = @ _ ;
2011-10-14 11:05:06 +02:00
$ self - > cmd ( "qm resume $vmid --skiplock" ) ;
2011-08-23 07:47:04 +02:00
}
sub assemble {
my ( $ self , $ task , $ vmid ) = @ _ ;
2016-03-09 14:34:03 +01:00
my $ conffile = PVE::QemuConfig - > config_file ( $ vmid ) ;
2011-08-23 07:47:04 +02:00
my $ outfile = "$task->{tmpdir}/qemu-server.conf" ;
2015-11-25 10:20:05 +01:00
my $ firewall_src = "/etc/pve/firewall/$vmid.fw" ;
my $ firewall_dest = "$task->{tmpdir}/qemu-server.fw" ;
my $ outfd = IO::File - > new ( ">$outfile" ) ||
die "unable to open '$outfile'" ;
my $ conffd = IO::File - > new ( $ conffile , 'r' ) ||
die "unable open '$conffile'" ;
my $ found_snapshot ;
while ( defined ( my $ line = <$conffd> ) ) {
next if $ line =~ m/^\#vzdump\#/ ; # just to be sure
next if $ line =~ m/^\#qmdump\#/ ; # just to be sure
if ( $ line =~ m/^\[.*\]\s*$/ ) {
$ found_snapshot = 1 ;
2011-08-23 07:47:04 +02:00
}
2015-11-25 10:20:05 +01:00
next if $ found_snapshot ; # skip all snapshots data
if ( $ line =~ m/^unused\d+:\s*(\S+)\s*/ ) {
$ self - > loginfo ( "skip unused drive '$1' (not included into backup)" ) ;
next ;
2011-08-23 07:47:04 +02:00
}
2015-11-25 10:20:05 +01:00
next if $ line =~ m/^lock:/ || $ line =~ m/^parent:/ ;
2012-12-12 15:35:26 +01:00
2015-11-25 10:20:05 +01:00
print $ outfd $ line ;
}
foreach my $ di ( @ { $ task - > { disks } } ) {
if ( $ di - > { type } eq 'block' || $ di - > { type } eq 'file' ) {
my $ storeid = $ di - > { storeid } || '' ;
my $ format = $ di - > { format } || '' ;
print $ outfd "#qmdump#map:$di->{virtdev}:$di->{qmdevice}:$storeid:$format:\n" ;
} else {
die "internal error" ;
2012-12-12 15:35:26 +01:00
}
2015-11-25 10:20:05 +01:00
}
2011-08-23 07:47:04 +02:00
2015-11-25 10:20:05 +01:00
if ( $ found_snapshot ) {
$ self - > loginfo ( "snapshots found (not included into backup)" ) ;
}
2014-12-10 06:40:21 +01:00
2015-11-25 10:20:05 +01:00
PVE::Tools:: file_copy ( $ firewall_src , $ firewall_dest ) if - f $ firewall_src ;
2011-08-23 07:47:04 +02:00
}
sub archive {
2012-02-07 10:40:28 +01:00
my ( $ self , $ task , $ vmid , $ filename , $ comp ) = @ _ ;
2011-08-23 07:47:04 +02:00
my $ conffile = "$task->{tmpdir}/qemu-server.conf" ;
2015-11-25 10:20:05 +01:00
my $ firewall = "$task->{tmpdir}/qemu-server.fw" ;
2011-08-23 07:47:04 +02:00
my $ opts = $ self - > { vzdump } - > { opts } ;
my $ starttime = time ( ) ;
2012-12-12 15:35:26 +01:00
my $ speed = 0 ;
if ( $ opts - > { bwlimit } ) {
2014-12-10 06:40:21 +01:00
$ speed = $ opts - > { bwlimit } * 1024 ;
2012-12-12 15:35:26 +01:00
}
2011-08-23 07:47:04 +02:00
2014-04-14 11:21:01 +02:00
my $ diskcount = scalar ( @ { $ task - > { disks } } ) ;
2016-03-07 12:41:12 +01:00
if ( PVE::QemuConfig - > is_template ( $ self - > { vmlist } - > { $ vmid } ) || ! $ diskcount ) {
2013-02-22 09:46:59 +01:00
my @ pathlist ;
foreach my $ di ( @ { $ task - > { disks } } ) {
if ( $ di - > { type } eq 'block' || $ di - > { type } eq 'file' ) {
push @ pathlist , "$di->{qmdevice}=$di->{path}" ;
} else {
die "implement me" ;
}
}
2014-04-14 11:21:01 +02:00
if ( ! $ diskcount ) {
$ self - > loginfo ( "backup contains no disks" ) ;
}
2013-02-22 09:46:59 +01:00
my $ outcmd ;
if ( $ comp ) {
2014-12-10 06:40:21 +01:00
$ outcmd = "exec:$comp" ;
2013-02-22 09:46:59 +01:00
} else {
2014-12-10 06:40:21 +01:00
$ outcmd = "exec:cat" ;
2013-02-22 09:46:59 +01:00
}
$ outcmd . = ">$filename" if ! $ opts - > { stdout } ;
2015-11-25 10:20:05 +01:00
my $ cmd = [ '/usr/bin/vma' , 'create' , '-v' , '-c' , $ conffile ] ;
push @$ cmd , '-c' , $ firewall if - e $ firewall ;
push @$ cmd , $ outcmd , @ pathlist ;
2013-02-22 09:46:59 +01:00
$ self - > loginfo ( "starting template backup" ) ;
$ self - > loginfo ( join ( ' ' , @$ cmd ) ) ;
if ( $ opts - > { stdout } ) {
$ self - > cmd ( $ cmd , output = > ">&=" . fileno ( $ opts - > { stdout } ) ) ;
} else {
$ self - > cmd ( $ cmd ) ;
}
return ;
}
2012-12-12 15:35:26 +01:00
my $ devlist = '' ;
2011-08-23 07:47:04 +02:00
foreach my $ di ( @ { $ task - > { disks } } ) {
if ( $ di - > { type } eq 'block' || $ di - > { type } eq 'file' ) {
2012-12-12 15:35:26 +01:00
$ devlist . = $ devlist ? ",$di->{qmdevice}" : $ di - > { qmdevice } ;
2011-08-23 07:47:04 +02:00
} else {
die "implement me" ;
}
}
2012-12-12 15:35:26 +01:00
my $ stop_after_backup ;
my $ resume_on_backup ;
my $ skiplock = 1 ;
2014-12-09 11:12:56 +01:00
my $ vm_is_running = PVE::QemuServer:: check_running ( $ vmid ) ;
if ( ! $ vm_is_running ) {
2012-12-12 15:35:26 +01:00
eval {
$ self - > loginfo ( "starting kvm to execute backup task" ) ;
2014-12-10 06:40:21 +01:00
PVE::QemuServer:: vm_start ( $ self - > { storecfg } , $ vmid , undef ,
2012-12-12 15:35:26 +01:00
$ skiplock , undef , 1 ) ;
if ( $ self - > { vm_was_running } ) {
$ resume_on_backup = 1 ;
} else {
$ stop_after_backup = 1 ;
}
} ;
if ( my $ err = $@ ) {
die $ err ;
}
2011-10-19 11:27:42 +02:00
}
2012-12-12 15:35:26 +01:00
my $ cpid ;
my $ interrupt_msg = "interrupted by signal\n" ;
eval {
$ SIG { INT } = $ SIG { TERM } = $ SIG { QUIT } = $ SIG { HUP } = $ SIG { PIPE } = sub {
die $ interrupt_msg ;
} ;
my $ qmpclient = PVE::QMPClient - > new ( ) ;
my $ uuid ;
my $ backup_cb = sub {
my ( $ vmid , $ resp ) = @ _ ;
2015-07-29 11:00:35 +02:00
$ uuid = $ resp - > { return } - > { UUID } ;
2012-12-12 15:35:26 +01:00
} ;
my $ outfh ;
if ( $ opts - > { stdout } ) {
$ outfh = $ opts - > { stdout } ;
} else {
$ outfh = IO::File - > new ( $ filename , "w" ) ||
die "unable to open file '$filename' - $!\n" ;
}
my $ outfileno ;
if ( $ comp ) {
my @ pipefd = POSIX:: pipe ( ) ;
$ cpid = fork ( ) ;
die "unable to fork worker - $!" if ! defined ( $ cpid ) ;
if ( $ cpid == 0 ) {
eval {
POSIX:: close ( $ pipefd [ 1 ] ) ;
# redirect STDIN
my $ fd = fileno ( STDIN ) ;
close STDIN ;
POSIX:: close ( 0 ) if $ fd != 0 ;
2014-12-10 06:40:21 +01:00
die "unable to redirect STDIN - $!"
2012-12-12 15:35:26 +01:00
if ! open ( STDIN , "<&" , $ pipefd [ 0 ] ) ;
2014-12-10 06:40:21 +01:00
2012-12-12 15:35:26 +01:00
# redirect STDOUT
$ fd = fileno ( STDOUT ) ;
close STDOUT ;
POSIX:: close ( 1 ) if $ fd != 1 ;
2014-12-10 06:40:21 +01:00
die "unable to redirect STDOUT - $!"
2012-12-12 15:35:26 +01:00
if ! open ( STDOUT , ">&" , fileno ( $ outfh ) ) ;
2014-12-10 06:40:21 +01:00
2012-12-12 15:35:26 +01:00
exec ( $ comp ) ;
die "fork compressor '$comp' failed\n" ;
} ;
if ( my $ err = $@ ) {
2013-02-28 10:47:55 +01:00
$ self - > logerr ( $ err ) ;
2014-12-10 06:40:21 +01:00
POSIX:: _exit ( 1 ) ;
2012-12-12 15:35:26 +01:00
}
2014-12-10 06:40:21 +01:00
POSIX:: _exit ( 0 ) ;
kill ( - 9 , $$ ) ;
2012-12-12 15:35:26 +01:00
} else {
POSIX:: close ( $ pipefd [ 0 ] ) ;
$ outfileno = $ pipefd [ 1 ] ;
2014-12-10 06:40:21 +01:00
}
2012-12-12 15:35:26 +01:00
} else {
$ outfileno = fileno ( $ outfh ) ;
}
my $ add_fd_cb = sub {
my ( $ vmid , $ resp ) = @ _ ;
2015-11-25 10:20:05 +01:00
my $ params = {
'backup-file' = > "/dev/fdname/backup" ,
speed = > $ speed ,
'config-file' = > $ conffile ,
devlist = > $ devlist
} ;
$ params - > { 'firewall-file' } = $ firewall if - e $ firewall ;
$ qmpclient - > queue_cmd ( $ vmid , $ backup_cb , 'backup' , %$ params ) ;
2012-12-12 15:35:26 +01:00
} ;
2014-12-10 06:40:21 +01:00
$ qmpclient - > queue_cmd ( $ vmid , $ add_fd_cb , 'getfd' ,
2012-12-12 15:35:26 +01:00
fd = > $ outfileno , fdname = > "backup" ) ;
2014-12-09 11:12:56 +01:00
if ( $ self - > { vmlist } - > { $ vmid } - > { agent } && $ vm_is_running ) {
2014-12-10 06:40:21 +01:00
eval { PVE::QemuServer:: vm_mon_cmd ( $ vmid , "guest-fsfreeze-freeze" ) ; } ;
2014-12-09 11:12:56 +01:00
if ( my $ err = $@ ) {
$ self - > logerr ( $ err ) ;
2014-12-10 06:40:21 +01:00
}
2014-12-09 11:12:56 +01:00
}
2014-12-10 06:40:21 +01:00
2012-12-12 15:35:26 +01:00
$ qmpclient - > queue_execute ( ) ;
2014-12-09 11:12:56 +01:00
if ( $ self - > { vmlist } - > { $ vmid } - > { agent } && $ vm_is_running ) {
2014-12-10 06:40:21 +01:00
eval { PVE::QemuServer:: vm_mon_cmd ( $ vmid , "guest-fsfreeze-thaw" ) ; } ;
2014-12-09 11:12:56 +01:00
if ( my $ err = $@ ) {
$ self - > logerr ( $ err ) ;
}
}
2014-12-10 06:40:21 +01:00
die $ qmpclient - > { errors } - > { $ vmid } if $ qmpclient - > { errors } - > { $ vmid } ;
2012-12-12 15:35:26 +01:00
if ( $ cpid ) {
2014-12-10 06:40:21 +01:00
POSIX:: close ( $ outfileno ) == 0 ||
2012-12-12 15:35:26 +01:00
die "close output file handle failed\n" ;
}
die "got no uuid for backup task\n" if ! $ uuid ;
$ self - > loginfo ( "started backup task '$uuid'" ) ;
if ( $ resume_on_backup ) {
$ self - > loginfo ( "resume VM" ) ;
PVE::QemuServer:: vm_mon_cmd ( $ vmid , 'cont' ) ;
}
my $ status ;
my $ starttime = time ( ) ;
my $ last_per = - 1 ;
2014-12-10 06:40:21 +01:00
my $ last_total = 0 ;
2012-12-12 15:35:26 +01:00
my $ last_zero = 0 ;
my $ last_transferred = 0 ;
my $ last_time = time ( ) ;
my $ transferred ;
while ( 1 ) {
$ status = PVE::QemuServer:: vm_mon_cmd ( $ vmid , 'query-backup' ) ;
2013-03-12 08:50:02 +01:00
my $ total = $ status - > { total } || 0 ;
$ transferred = $ status - > { transferred } || 0 ;
2012-12-12 15:35:26 +01:00
my $ per = $ total ? int ( ( $ transferred * 100 ) / $ total ) : 0 ;
my $ zero = $ status - > { 'zero-bytes' } || 0 ;
my $ zero_per = $ total ? int ( ( $ zero * 100 ) / $ total ) : 0 ;
2014-12-10 06:40:21 +01:00
2013-03-12 08:50:02 +01:00
die "got unexpected uuid\n" if ! $ status - > { uuid } || ( $ status - > { uuid } ne $ uuid ) ;
2012-12-12 15:35:26 +01:00
my $ ctime = time ( ) ;
my $ duration = $ ctime - $ starttime ;
my $ rbytes = $ transferred - $ last_transferred ;
my $ wbytes = $ rbytes - ( $ zero - $ last_zero ) ;
my $ timediff = ( $ ctime - $ last_time ) || 1 ; # fixme
2014-12-10 06:40:21 +01:00
my $ mbps_read = ( $ rbytes > 0 ) ?
2012-12-12 15:35:26 +01:00
int ( ( $ rbytes /$timediff)/ ( 1000 * 1000 ) ) : 0 ;
2014-12-10 06:40:21 +01:00
my $ mbps_write = ( $ wbytes > 0 ) ?
2012-12-12 15:35:26 +01:00
int ( ( $ wbytes /$timediff)/ ( 1000 * 1000 ) ) : 0 ;
my $ statusline = "status: $per% ($transferred/$total), " .
"sparse ${zero_per}% ($zero), duration $duration, " .
"$mbps_read/$mbps_write MB/s" ;
2013-03-12 08:50:02 +01:00
my $ res = $ status - > { status } || 'unknown' ;
if ( $ res ne 'active' ) {
2012-12-12 15:35:26 +01:00
$ self - > loginfo ( $ statusline ) ;
die ( ( $ status - > { errmsg } || "unknown error" ) . "\n" )
2013-03-12 08:50:02 +01:00
if $ res eq 'error' ;
die "got unexpected status '$res'\n"
if $ res ne 'done' ;
die "got wrong number of transfered bytes ($total != $transferred)\n"
if ( $ res eq 'done' ) && ( $ total != $ transferred ) ;
2012-12-12 15:35:26 +01:00
last ;
}
if ( $ per != $ last_per && ( $ timediff > 2 ) ) {
$ self - > loginfo ( $ statusline ) ;
$ last_per = $ per ;
2014-12-10 06:40:21 +01:00
$ last_total = $ total if $ total ;
2012-12-12 15:35:26 +01:00
$ last_zero = $ zero if $ zero ;
$ last_transferred = $ transferred if $ transferred ;
$ last_time = $ ctime ;
}
sleep ( 1 ) ;
}
my $ duration = time ( ) - $ starttime ;
if ( $ transferred && $ duration ) {
my $ mb = int ( $ transferred / ( 1000 * 1000 ) ) ;
my $ mbps = int ( ( $ transferred /$duration)/ ( 1000 * 1000 ) ) ;
$ self - > loginfo ( "transferred $mb MB in $duration seconds ($mbps MB/s)" ) ;
}
} ;
my $ err = $@ ;
2013-01-16 13:21:27 +01:00
if ( $ err ) {
2013-02-28 10:47:55 +01:00
$ self - > logerr ( $ err ) ;
2013-01-16 13:21:27 +01:00
$ self - > loginfo ( "aborting backup job" ) ;
2013-02-20 10:48:52 +01:00
eval { PVE::QemuServer:: vm_mon_cmd ( $ vmid , 'backup-cancel' ) ; } ;
2013-02-28 10:47:55 +01:00
if ( my $ err1 = $@ ) {
$ self - > logerr ( $ err1 ) ;
}
2013-01-16 13:21:27 +01:00
}
2012-12-12 15:35:26 +01:00
if ( $ stop_after_backup ) {
# stop if not running
eval {
my $ resp = PVE::QemuServer:: vm_mon_cmd ( $ vmid , 'query-status' ) ;
my $ status = $ resp && $ resp - > { status } ? $ resp - > { status } : 'unknown' ;
if ( $ status eq 'prelaunch' ) {
2013-01-16 13:21:27 +01:00
$ self - > loginfo ( "stopping kvm after backup task" ) ;
2012-12-12 15:35:26 +01:00
PVE::QemuServer:: vm_stop ( $ self - > { storecfg } , $ vmid , $ skiplock ) ;
} else {
$ self - > loginfo ( "kvm status changed after backup ('$status')" .
" - keep VM running" ) ;
}
}
2014-12-10 06:40:21 +01:00
}
2012-12-12 15:35:26 +01:00
if ( $ err ) {
2014-12-10 06:40:21 +01:00
if ( $ cpid ) {
kill ( 9 , $ cpid ) ;
2012-12-12 15:35:26 +01:00
waitpid ( $ cpid , 0 ) ;
}
die $ err ;
}
if ( $ cpid && ( waitpid ( $ cpid , 0 ) > 0 ) ) {
my $ stat = $? ;
my $ ec = $ stat >> 8 ;
my $ signal = $ stat & 127 ;
if ( $ ec || $ signal ) {
2014-12-10 06:40:21 +01:00
die "$comp failed - wrong exit status $ec" .
2012-12-12 15:35:26 +01:00
( $ signal ? " (signal $signal)\n" : "\n" ) ;
}
}
}
sub snapshot {
my ( $ self , $ task , $ vmid ) = @ _ ;
# nothing to do
2011-08-23 07:47:04 +02:00
}
sub cleanup {
my ( $ self , $ task , $ vmid ) = @ _ ;
2012-12-12 15:35:26 +01:00
# nothing to do ?
2011-08-23 07:47:04 +02:00
}
1 ;