]> git.proxmox.com Git - pve-guest-common.git/blobdiff - PVE/ReplicationState.pm
Add function: swap source and target in replication config
[pve-guest-common.git] / PVE / ReplicationState.pm
index f82bb5c1a613f3e832a6f74105c7d8f901daa023..085119574dfbe02ecc2f43511e9df8612a05bfc3 100644 (file)
@@ -147,6 +147,18 @@ sub record_job_start {
     write_job_state($jobcfg, $state);
 }
 
+sub delete_guest_states {
+    my ($vmid) = @_;
+
+    my $code = sub {
+       my $stateobj = read_state();
+       delete $stateobj->{$vmid};
+       PVE::Tools::file_set_contents($state_path, encode_json($stateobj));
+    };
+
+    PVE::Tools::lock_file($state_lock, 10, $code);
+}
+
 sub record_job_end {
     my ($jobcfg, $state, $start_time, $duration, $err) = @_;
 
@@ -185,6 +197,7 @@ sub purge_old_states {
     my $local_node = PVE::INotify::nodename();
 
     my $cfg = PVE::ReplicationConfig->new();
+    PVE::Cluster::cfs_update(1); # fail if we cannot query the vm list
     my $vms = PVE::Cluster::get_vmlist();
 
     my $used_tids = {};
@@ -215,6 +228,7 @@ sub purge_old_states {
 }
 
 sub job_status {
+    my ($get_disabled) = @_;
 
     my $local_node = PVE::INotify::nodename();
 
@@ -238,11 +252,12 @@ sub job_status {
        # only consider guest on local node
        next if $vms->{ids}->{$vmid}->{node} ne $local_node;
 
+       my $target = $jobcfg->{target};
        if (!$jobcfg->{remove_job}) {
            # never sync to local node
-           next if $jobcfg->{target} eq $local_node;
+           next if $target eq $local_node;
 
-           next if $jobcfg->{disable};
+           next if !$get_disabled && $jobcfg->{disable};
        }
 
        my $state = extract_job_state($stateobj, $jobcfg);
@@ -257,7 +272,10 @@ sub job_status {
            # todo: consider fail_count? How many retries?
        } else  {
            if (my $fail_count = $state->{fail_count}) {
-               $next_sync = $state->{last_try} + 60*($fail_count < 3 ? 5*$fail_count : 30);
+               my $members = PVE::Cluster::get_members();
+               if (!$fail_count || ($members->{$target} && $members->{$target}->{online})) {
+                   $next_sync = $state->{last_try} + 60*($fail_count < 3 ? 5*$fail_count : 30);
+               }
            } else {
                my $schedule =  $jobcfg->{schedule} || '*/15';
                my $calspec = PVE::CalendarEvent::parse_calendar_event($schedule);
@@ -267,6 +285,11 @@ sub job_status {
 
        $jobcfg->{next_sync} = $next_sync;
 
+       if (!defined($jobcfg->{source}) || $jobcfg->{source} ne $local_node) {
+           $jobcfg->{source} = $cfg->{ids}->{$jobid}->{source} = $local_node;
+           PVE::ReplicationConfig::write($cfg);
+       }
+
        $jobs->{$jobid} = $jobcfg;
     }
 
@@ -283,7 +306,7 @@ sub get_next_job {
        my $jobb = $jobs->{$b};
        my $sa =  $joba->{state};
        my $sb =  $jobb->{state};
-       my $res = $sa->{last_iteration} cmp $sb->{last_iteration};
+       my $res = $sa->{last_iteration} <=> $sb->{last_iteration};
        return $res if $res != 0;
        $res = $joba->{next_sync} <=> $jobb->{next_sync};
        return $res if $res != 0;
@@ -301,4 +324,24 @@ sub get_next_job {
     return undef;
 }
 
+sub schedule_job_now {
+    my ($jobcfg) = @_;
+
+    PVE::GuestHelpers::guest_migration_lock($jobcfg->{guest}, undef, sub {
+       PVE::Tools::lock_file($state_lock, 10, sub {
+           my $stateobj = read_state();
+           my $vmid = $jobcfg->{guest};
+           my $plugin = PVE::ReplicationConfig->lookup($jobcfg->{type});
+           my $tid = $plugin->get_unique_target_id($jobcfg);
+           # no not modify anything if there is no state
+           return if !defined($stateobj->{$vmid}->{$tid});
+
+           my $state = read_job_state($jobcfg);
+           $state->{last_try} = 0;
+           write_job_state($jobcfg, $state);
+       });
+       die $@ if $@;
+    });
+}
+
 1;