]> git.proxmox.com Git - qemu-server.git/commitdiff
vzdump: factor out VM powerstate handling and qmp backup cancel
authorThomas Lamprecht <t.lamprecht@proxmox.com>
Thu, 19 Mar 2020 17:41:43 +0000 (18:41 +0100)
committerThomas Lamprecht <t.lamprecht@proxmox.com>
Thu, 19 Mar 2020 17:41:43 +0000 (18:41 +0100)
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
PVE/VZDump/QemuServer.pm

index 69d373461c9aabe7f289b57634497aa79d9ce92a..9ca745f69e4ca6e1ef9cd7ce4aeabbeb851a78b3 100644 (file)
@@ -383,26 +383,8 @@ sub archive_pbs {
     # get list early so we die on unkown drive types before doing anything
     my $devlist = _get_task_devlist($task);
 
-    my $stop_after_backup;
-    my $resume_on_backup;
-
-    my $skiplock = 1;
-    my $vm_is_running = PVE::QemuServer::check_running($vmid);
-    if (!$vm_is_running) {
-       eval {
-           $self->loginfo("starting kvm to execute backup task");
-           PVE::QemuServer::vm_start($self->{storecfg}, $vmid, undef,
-                                     $skiplock, undef, 1);
-           if ($self->{vm_was_running}) {
-               $resume_on_backup = 1;
-           } else {
-               $stop_after_backup = 1;
-           }
-       };
-       if (my $err = $@) {
-           die $err;
-       }
-    }
+    my ($stop_after_backup, $resume_on_backup) = $self->handle_vm_powerstate($vmid);
+    $self->enforce_vm_running_for_backup($vmid);
 
     my $backup_job_uuid;
 
@@ -442,46 +424,16 @@ sub archive_pbs {
 
        $self->loginfo("started backup task '$backup_job_uuid'");
 
-       if ($resume_on_backup) {
-           if (my $stoptime = $task->{vmstoptime}) {
-               my $delay = time() - $task->{vmstoptime};
-               $task->{vmstoptime} = undef; # avoid printing 'online after ..' twice
-               $self->loginfo("resuming VM again after $delay seconds");
-           } else {
-               $self->loginfo("resuming VM again");
-           }
-           mon_cmd($vmid, 'cont');
-       }
+       $self->resume_vm_after_job_start($task, $vmid);
 
        $query_backup_status_loop->($self, $vmid, $backup_job_uuid);
     };
     my $err = $@;
-
     if ($err) {
        $self->logerr($err);
-       if (defined($backup_job_uuid)) {
-           $self->loginfo("aborting backup job");
-           eval { mon_cmd($vmid, 'backup-cancel'); };
-           if (my $err1 = $@) {
-               $self->logerr($err1);
-           }
-       }
-    }
-
-    if ($stop_after_backup) {
-       # stop if not running
-       eval {
-           my $resp = mon_cmd($vmid, 'query-status');
-           my $status = $resp && $resp->{status} ?  $resp->{status} : 'unknown';
-           if ($status eq 'prelaunch') {
-               $self->loginfo("stopping kvm after backup task");
-               PVE::QemuServer::vm_stop($self->{storecfg}, $vmid, $skiplock);
-           } else {
-               $self->loginfo("kvm status changed after backup ('$status')" .
-                              " - keep VM running");
-           }
-       }
+       $self->mon_backup_cancel($vmid) if defined($backup_job_uuid);
     }
+    $self->restore_vm_power_state($vmid);
 
     die $err if $err;
 }
@@ -585,26 +537,7 @@ sub archive_vma {
 
     my $devlist = _get_task_devlist($task);
 
-    my $stop_after_backup;
-    my $resume_on_backup;
-
-    my $skiplock = 1;
-    my $vm_is_running = PVE::QemuServer::check_running($vmid);
-    if (!$vm_is_running) {
-       eval {
-           $self->loginfo("starting kvm to execute backup task");
-           PVE::QemuServer::vm_start($self->{storecfg}, $vmid, undef,
-                                     $skiplock, undef, 1);
-           if ($self->{vm_was_running}) {
-               $resume_on_backup = 1;
-           } else {
-               $stop_after_backup = 1;
-           }
-       };
-       if (my $err = $@) {
-           die $err;
-       }
-    }
+    $self->enforce_vm_running_for_backup($vmid);
 
     my $cpid;
     my $backup_job_uuid;
@@ -672,46 +605,17 @@ sub archive_vma {
 
        $self->loginfo("started backup task '$backup_job_uuid'");
 
-       if ($resume_on_backup) {
-           if (my $stoptime = $task->{vmstoptime}) {
-               my $delay = time() - $task->{vmstoptime};
-               $task->{vmstoptime} = undef; # avoid printing 'online after ..' twice
-               $self->loginfo("resuming VM again after $delay seconds");
-           } else {
-               $self->loginfo("resuming VM again");
-           }
-           mon_cmd($vmid, 'cont');
-       }
+       $self->resume_vm_after_job_start($task, $vmid);
 
        $query_backup_status_loop->($self, $vmid, $backup_job_uuid);
     };
     my $err = $@;
-
     if ($err) {
        $self->logerr($err);
-       if (defined($backup_job_uuid)) {
-           $self->loginfo("aborting backup job");
-           eval { mon_cmd($vmid, 'backup-cancel'); };
-           if (my $err1 = $@) {
-               $self->logerr($err1);
-           }
-       }
+       $self->mon_backup_cancel($vmid) if defined($backup_job_uuid);
     }
 
-    if ($stop_after_backup) {
-       # stop if not running
-       eval {
-           my $resp = mon_cmd($vmid, 'query-status');
-           my $status = $resp && $resp->{status} ?  $resp->{status} : 'unknown';
-           if ($status eq 'prelaunch') {
-               $self->loginfo("stopping kvm after backup task");
-               PVE::QemuServer::vm_stop($self->{storecfg}, $vmid, $skiplock);
-           } else {
-               $self->loginfo("kvm status changed after backup ('$status')" .
-                              " - keep VM running");
-           }
-       }
-    }
+    $self->restore_vm_power_state($vmid);
 
     if ($err) {
        if ($cpid) {
@@ -772,6 +676,68 @@ sub qga_fs_thaw {
     $self->logerr($@) if $@;
 }
 
+# we need a running QEMU/KVM process for backup, starts a paused (prelaunch)
+# one if VM isn't already running
+sub enforce_vm_running_for_backup {
+    my ($self, $vmid) = @_;
+
+    if (PVE::QemuServer::check_running($vmid)) {
+       $self->{vm_was_running} = 1;
+       return;
+    }
+
+    eval {
+       $self->loginfo("starting kvm to execute backup task");
+       # start with skiplock
+       PVE::QemuServer::vm_start($self->{storecfg}, $vmid, undef, 1, undef, 1);
+    };
+    die $@ if $@;
+}
+
+# resume VM againe once we got in a clear state (stop mode backup of running VM)
+sub resume_vm_after_job_start {
+    my ($self, $task, $vmid) = @_;
+
+    return if !$self->{vm_was_running};
+
+    if (my $stoptime = $task->{vmstoptime}) {
+       my $delay = time() - $task->{vmstoptime};
+       $task->{vmstoptime} = undef; # avoid printing 'online after ..' twice
+       $self->loginfo("resuming VM again after $delay seconds");
+    } else {
+       $self->loginfo("resuming VM again");
+    }
+    mon_cmd($vmid, 'cont');
+}
+
+# stop again if VM was not running before
+sub restore_vm_power_state {
+    my ($self, $vmid) = @_;
+
+    # we always let VMs keep running
+    return if $self->{vm_was_running};
+
+    eval {
+       my $resp = mon_cmd($vmid, 'query-status');
+       my $status = $resp && $resp->{status} ?  $resp->{status} : 'unknown';
+       if ($status eq 'prelaunch') {
+           $self->loginfo("stopping kvm after backup task");
+           PVE::QemuServer::vm_stop($self->{storecfg}, $vmid, 1);
+       } else {
+           $self->loginfo("kvm status changed after backup ('$status') - keep VM running");
+       }
+    };
+    warn $@ if $@;
+}
+
+sub mon_backup_cancel {
+    my ($self, $vmid) = @_;
+
+    $self->loginfo("aborting backup job");
+    eval { mon_cmd($vmid, 'backup-cancel') };
+    $self->logerr($@) if $@;
+}
+
 sub snapshot {
     my ($self, $task, $vmid) = @_;