1 package PVE
::ReplicationState
;
9 use PVE
::ReplicationConfig
;
11 # Note: regression tests can overwrite $state_path for testing
12 our $state_path = "/var/lib/pve-manager/pve-replication-state.json";
13 our $state_lock = "/var/lib/pve-manager/pve-replication-state.lck";
15 # Note: We use PVE::Tools::file_set_contents to write state file atomically,
16 # so read_state() always returns an consistent copy (even when not locked).
20 return {} if ! -e
$state_path;
22 my $raw = PVE
::Tools
::file_get_contents
($state_path);
24 return {} if $raw eq '';
27 if ($raw =~ m/^({.*})$/) {
28 return decode_json
($1);
31 die "invalid json data in '$state_path'\n";
34 sub extract_job_state
{
35 my ($stateobj, $jobcfg) = @_;
37 my $plugin = PVE
::ReplicationConfig-
>lookup($jobcfg->{type
});
39 my $vmid = $jobcfg->{guest
};
40 my $tid = $plugin->get_unique_target_id($jobcfg);
41 my $state = $stateobj->{$vmid}->{$tid};
43 $state = {} if !$state;
45 $state->{last_iteration
} //= 0;
46 $state->{last_try
} //= 0; # last sync start time
47 $state->{last_sync
} //= 0; # last successful sync start time
48 $state->{fail_count
} //= 0;
56 my $stateobj = read_state
();
57 return extract_job_state
($stateobj, $jobcfg);
61 my ($jobcfg, $state) = @_;
63 my $plugin = PVE
::ReplicationConfig-
>lookup($jobcfg->{type
});
65 my $vmid = $jobcfg->{guest
};
66 my $tid = $plugin->get_unique_target_id($jobcfg);
70 my $stateobj = read_state
();
71 # Note: tuple ($vmid, $tid) is unique
72 $stateobj->{$vmid}->{$tid} = $state;
74 PVE
::Tools
::file_set_contents
($state_path, encode_json
($stateobj));
78 PVE
::Tools
::lock_file
($state_lock, 10, $update);
82 # make sure we have guest_migration_lock during update
83 PVE
::GuestHelpers
::guest_migration_lock
($vmid, undef, $code);
86 sub replication_snapshot_name
{
87 my ($jobid, $last_sync) = @_;
89 my $prefix = "__replicate_${jobid}_";
90 my $snapname = "${prefix}${last_sync}__";
92 wantarray ?
($prefix, $snapname) : $snapname;