5
0
mirror of git://git.proxmox.com/git/pve-guest-common.git synced 2024-12-24 21:34:13 +03:00
pve-guest-common/PVE/ReplicationState.pm

96 lines
2.2 KiB
Perl
Raw Normal View History

package PVE::ReplicationState;
use warnings;
use strict;
use JSON;
use PVE::Tools;
use PVE::GuestHelpers;
use PVE::ReplicationConfig;
# Note: regression tests can overwrite $state_path for testing
our $state_path = "/var/lib/pve-manager/pve-replication-state.json";
our $state_lock = "/var/lib/pve-manager/pve-replication-state.lck";
# Note: We use PVE::Tools::file_set_contents to write state file atomically,
# so read_state() always returns an consistent copy (even when not locked).
sub read_state {
return {} if ! -e $state_path;
my $raw = PVE::Tools::file_get_contents($state_path);
return {} if $raw eq '';
# untaint $raw
if ($raw =~ m/^({.*})$/) {
return decode_json($1);
}
die "invalid json data in '$state_path'\n";
}
sub extract_job_state {
my ($stateobj, $jobcfg) = @_;
my $plugin = PVE::ReplicationConfig->lookup($jobcfg->{type});
my $vmid = $jobcfg->{guest};
my $tid = $plugin->get_unique_target_id($jobcfg);
my $state = $stateobj->{$vmid}->{$tid};
$state = {} if !$state;
$state->{last_iteration} //= 0;
$state->{last_try} //= 0; # last sync start time
$state->{last_sync} //= 0; # last successful sync start time
$state->{fail_count} //= 0;
return $state;
}
sub read_job_state {
my ($jobcfg) = @_;
my $stateobj = read_state();
return extract_job_state($stateobj, $jobcfg);
}
sub write_job_state {
my ($jobcfg, $state) = @_;
my $plugin = PVE::ReplicationConfig->lookup($jobcfg->{type});
my $vmid = $jobcfg->{guest};
my $tid = $plugin->get_unique_target_id($jobcfg);
my $update = sub {
my $stateobj = read_state();
# Note: tuple ($vmid, $tid) is unique
$stateobj->{$vmid}->{$tid} = $state;
PVE::Tools::file_set_contents($state_path, encode_json($stateobj));
};
my $code = sub {
PVE::Tools::lock_file($state_lock, 10, $update);
die $@ if $@;
};
# make sure we have guest_migration_lock during update
PVE::GuestHelpers::guest_migration_lock($vmid, undef, $code);
}
sub replication_snapshot_name {
my ($jobid, $last_sync) = @_;
my $prefix = "__replicate_${jobid}_";
my $snapname = "${prefix}${last_sync}__";
wantarray ? ($prefix, $snapname) : $snapname;
}
1;