[pve-devel] [PATCH v3 pve-manager 22/23] PVE::API2::ReplicationConfig - implement delete

Dietmar Maurer dietmar at proxmox.com
Tue May 30 15:20:19 CEST 2017


We just set the remove_job property in the configuration. Actual removal
is done asynchronous inside replicate().

Signed-off-by: Dietmar Maurer <dietmar at proxmox.com>
---
 PVE/API2/ReplicationConfig.pm | 24 ++++++++---------
 PVE/CLI/pvesr.pm              |  9 ++++++-
 PVE/Replication.pm            | 62 +++++++++++++++++++++++++++++++++++--------
 3 files changed, 71 insertions(+), 24 deletions(-)

diff --git a/PVE/API2/ReplicationConfig.pm b/PVE/API2/ReplicationConfig.pm
index 6f4de385..0095bf37 100644
--- a/PVE/API2/ReplicationConfig.pm
+++ b/PVE/API2/ReplicationConfig.pm
@@ -4,7 +4,7 @@ use warnings;
 use strict;
 
 use PVE::Tools qw(extract_param);
-use PVE::Exception qw(raise_perm_exc);
+use PVE::Exception qw(raise_perm_exc raise_param_exc);
 use PVE::JSONSchema qw(get_standard_option);
 use PVE::RPCEnvironment;
 use PVE::ReplicationConfig;
@@ -112,7 +112,6 @@ __PACKAGE__->register_method ({
 	my $code = sub {
 	    my $cfg = PVE::ReplicationConfig->new();
 
-	    #die "replication job for guest '$param->{guest}' to target '$param->{target}' already exists\n"
 	    die "replication job '$id' already exists\n"
 		if $cfg->{ids}->{$id};
 
@@ -171,7 +170,7 @@ __PACKAGE__->register_method ({
     protected => 1,
     path => '{id}',
     method => 'DELETE',
-    description => "Delete replication job",
+    description => "Mark replication job for removal.",
     permissions => {
 	check => ['perm', '/storage', ['Datastore.Allocate']],
     },
@@ -191,21 +190,21 @@ __PACKAGE__->register_method ({
     code => sub {
 	my ($param) = @_;
 
-	my $id = extract_param($param, 'id');
-
 	my $code = sub {
 	    my $cfg = PVE::ReplicationConfig->new();
 
-	    my $data = $cfg->{ids}->{$id};
-	    die "no such job '$id'\n" if !$data;
+	    my $id = $param->{id};
 
-	    if (!$param->{keep}) {
-		# fixme: cleanup data at target
+	    my $jobcfg = $cfg->{ids}->{$id};
+	    die "no such job '$id'\n" if !$jobcfg;
 
+	    if (!$param->{keep} && $jobcfg->{type} eq 'local') {
+		# remove local snapshots and remote volumes
+		$jobcfg->{remove_job} = 'full';
+	    } else {
+		# only remove local snapshots
+		$jobcfg->{remove_job} = 'local';
 	    }
-	    # fixme: cleanup snapshots
-
-	    delete $cfg->{ids}->{$id};
 
 	    $cfg->write();
 	};
@@ -214,4 +213,5 @@ __PACKAGE__->register_method ({
 
 	return undef;
     }});
+
 1;
diff --git a/PVE/CLI/pvesr.pm b/PVE/CLI/pvesr.pm
index 97ec2b52..93f1a2db 100644
--- a/PVE/CLI/pvesr.pm
+++ b/PVE/CLI/pvesr.pm
@@ -37,6 +37,12 @@ __PACKAGE__->register_method ({
 	    vmid => get_standard_option('pve-vmid', { completion => \&PVE::Cluster::complete_vmid }),
 	    'extra-args' => get_standard_option('extra-args', {
 		description => "The list of volume IDs to consider." }),
+	    force => {
+		description => "Allow to remove all existion volumes (empty volume list).",
+		type => 'boolean',
+		optional => 1,
+		default => 0,
+	    },
 	    last_sync => {
 		description => "Time (UNIX epoch) of last successful sync. If not specified, all replication snapshots get removed.",
 		type => 'integer',
@@ -65,7 +71,8 @@ __PACKAGE__->register_method ({
 
 	my $volids = [];
 
-	die "no volumes specified\n" if !scalar(@{$param->{'extra-args'}});
+	die "no volumes specified\n"
+	    if !$param->{force} && !scalar(@{$param->{'extra-args'}});
 
 	foreach my $volid (@{$param->{'extra-args'}}) {
 
diff --git a/PVE/Replication.pm b/PVE/Replication.pm
index 711b08ff..01111787 100644
--- a/PVE/Replication.pm
+++ b/PVE/Replication.pm
@@ -103,15 +103,22 @@ sub job_status {
 	$jobcfg->{vmtype} = $vms->{ids}->{$vmid}->{type};
 
 	my $next_sync = 0;
-	if (my $fail_count = $state->{fail_count}) {
-	    if ($fail_count < 3) {
-		$next_sync = $state->{last_try} + 5*60*$fail_count;
+
+	if ($jobcfg->{remove_job}) {
+	    $next_sync = 1; # lowest possible value
+	    # todo: consider fail_count? How many retries?
+	} else  {
+	    if (my $fail_count = $state->{fail_count}) {
+		if ($fail_count < 3) {
+		    $next_sync = $state->{last_try} + 5*60*$fail_count;
+		}
+	    } else {
+		my $schedule =  $jobcfg->{schedule} || '*/15';
+		my $calspec = PVE::CalendarEvent::parse_calendar_event($schedule);
+		$next_sync = PVE::CalendarEvent::compute_next_event($calspec, $state->{last_try}) // 0;
 	    }
-	} else {
-	    my $schedule =  $jobcfg->{schedule} || '*/15';
-	    my $calspec = PVE::CalendarEvent::parse_calendar_event($schedule);
-	    $next_sync = PVE::CalendarEvent::compute_next_event($calspec, $state->{last_try}) // 0;
 	}
+
 	$jobcfg->{next_sync} = $next_sync;
 
 	$jobs->{$jobid} = $jobcfg;
@@ -168,11 +175,14 @@ sub replication_snapshot_name {
 }
 
 sub remote_prepare_local_job {
-    my ($ssh_info, $jobid, $vmid, $volumes, $last_sync) = @_;
+    my ($ssh_info, $jobid, $vmid, $volumes, $last_sync, $force) = @_;
 
     my $ssh_cmd = PVE::Cluster::ssh_info_to_command($ssh_info);
-    my $cmd = [@$ssh_cmd, '--', 'pvesr', 'prepare-local-job', $jobid,
-	       $vmid, @$volumes, '--last_sync', $last_sync];
+    my $cmd = [@$ssh_cmd, '--', 'pvesr', 'prepare-local-job', $jobid, $vmid];
+    push @$cmd, @$volumes if scalar(@$volumes);
+
+    push @$cmd, '--last_sync', $last_sync;
+    push @$cmd, '--force' if $force;
 
     my $remote_snapshots;
 
@@ -231,6 +241,18 @@ sub replicate_volume {
 				  $base_snapshot, $sync_snapname);
 }
 
+sub delete_job {
+    my ($jobid) = @_;
+
+    my $code = sub {
+	my $cfg = PVE::ReplicationConfig->new();
+	delete $cfg->{ids}->{$jobid};
+	$cfg->write();
+    };
+
+    PVE::ReplicationConfig::lock($code);
+}
+
 sub replicate {
     my ($jobcfg, $last_sync, $start_time, $logfunc) = @_;
 
@@ -284,9 +306,27 @@ sub replicate {
     $logfunc->($start_time, "$jobid: guest => $vmid, type => $vmtype, running => $running");
     $logfunc->($start_time, "$jobid: volumes => " . join(',', @$sorted_volids));
 
+    if (my $remove_job = $jobcfg->{remove_job}) {
+
+	$logfunc->($start_time, "$jobid: start job removal - mode '${remove_job}'");
+
+	if ($remove_job eq 'full') {
+	    # remove all remote volumes
+	    remote_prepare_local_job($ssh_info, $jobid, $vmid, [], 0, 1);
+
+	}
+	# remove all local replication snapshots (lastsync => 0)
+	prepare($storecfg, $sorted_volids, $jobid, 0, $start_time, $logfunc);
+
+	delete_job($jobid); # update config
+	$logfunc->($start_time, "$jobid: job removed");
+
+	return;
+    }
+
     # prepare remote side
     my $remote_snapshots = remote_prepare_local_job(
-	$ssh_info, $jobid, $vmid, $volumes, $last_sync);
+	$ssh_info, $jobid, $vmid, $sorted_volids, $last_sync);
 
     # test if we have a replication_ snapshot from last sync
     # and remove all other/stale replication snapshots
-- 
2.11.0




More information about the pve-devel mailing list