[pve-devel] [PATCH pve-guest-common 1/2] PVE::ReplicationState - new helper class to read/write replication state
Dietmar Maurer
dietmar at proxmox.com
Fri Jun 2 10:20:22 CEST 2017
Signed-off-by: Dietmar Maurer <dietmar at proxmox.com>
---
Makefile | 1 +
PVE/ReplicationState.pm | 81 +++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 82 insertions(+)
create mode 100644 PVE/ReplicationState.pm
diff --git a/Makefile b/Makefile
index cf7bd1a..143a6de 100644
--- a/Makefile
+++ b/Makefile
@@ -25,6 +25,7 @@ install: PVE
install -m 0644 PVE/AbstractConfig.pm ${PERL5DIR}/PVE/
install -m 0644 PVE/AbstractMigrate.pm ${PERL5DIR}/PVE/
install -m 0644 PVE/ReplicationConfig.pm ${PERL5DIR}/PVE/
+ install -m 0644 PVE/ReplicationState.pm ${PERL5DIR}/PVE/
install -d ${PERL5DIR}/PVE/VZDump
install -m 0644 PVE/VZDump/Plugin.pm ${PERL5DIR}/PVE/VZDump/
diff --git a/PVE/ReplicationState.pm b/PVE/ReplicationState.pm
new file mode 100644
index 0000000..cd7dc69
--- /dev/null
+++ b/PVE/ReplicationState.pm
@@ -0,0 +1,81 @@
+package PVE::ReplicationState;
+
+use warnings;
+use strict;
+use JSON;
+
+use PVE::Tools;
+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 $code = 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));
+ };
+
+ PVE::Tools::lock_file($state_lock, 10, $code);
+ die $@ if $@;
+}
+
+1;
--
2.11.0
More information about the pve-devel
mailing list