]> git.proxmox.com Git - pve-guest-common.git/blame - PVE/ReplicationState.pm
PVE::ReplicationConfig - new helper parse_replication_job_id
[pve-guest-common.git] / PVE / ReplicationState.pm
CommitLineData
3f7cacff
DM
1package PVE::ReplicationState;
2
3use warnings;
4use strict;
5use JSON;
6
7use PVE::Tools;
90c07bf7 8use PVE::GuestHelpers;
3f7cacff
DM
9use PVE::ReplicationConfig;
10
3f7cacff
DM
11# Note: regression tests can overwrite $state_path for testing
12our $state_path = "/var/lib/pve-manager/pve-replication-state.json";
13our $state_lock = "/var/lib/pve-manager/pve-replication-state.lck";
14
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).
17
18sub read_state {
19
20 return {} if ! -e $state_path;
21
22 my $raw = PVE::Tools::file_get_contents($state_path);
23
24 return {} if $raw eq '';
25
26 # untaint $raw
27 if ($raw =~ m/^({.*})$/) {
28 return decode_json($1);
29 }
30
31 die "invalid json data in '$state_path'\n";
32}
33
34sub extract_job_state {
35 my ($stateobj, $jobcfg) = @_;
36
37 my $plugin = PVE::ReplicationConfig->lookup($jobcfg->{type});
38
39 my $vmid = $jobcfg->{guest};
40 my $tid = $plugin->get_unique_target_id($jobcfg);
41 my $state = $stateobj->{$vmid}->{$tid};
42
43 $state = {} if !$state;
44
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;
49
50 return $state;
51}
52
53sub read_job_state {
54 my ($jobcfg) = @_;
55
56 my $stateobj = read_state();
57 return extract_job_state($stateobj, $jobcfg);
58}
59
60sub write_job_state {
61 my ($jobcfg, $state) = @_;
62
63 my $plugin = PVE::ReplicationConfig->lookup($jobcfg->{type});
64
65 my $vmid = $jobcfg->{guest};
66 my $tid = $plugin->get_unique_target_id($jobcfg);
67
90c07bf7 68 my $update = sub {
3f7cacff
DM
69
70 my $stateobj = read_state();
71 # Note: tuple ($vmid, $tid) is unique
72 $stateobj->{$vmid}->{$tid} = $state;
73
74 PVE::Tools::file_set_contents($state_path, encode_json($stateobj));
75 };
76
90c07bf7
DM
77 my $code = sub {
78 PVE::Tools::lock_file($state_lock, 10, $update);
79 die $@ if $@;
80 };
81
82 # make sure we have guest_migration_lock during update
83 PVE::GuestHelpers::guest_migration_lock($vmid, undef, $code);
3f7cacff
DM
84}
85
861;