From b76774e57fe66a483a7544ec5a05ba2e998eb836 Mon Sep 17 00:00:00 2001 From: Wolfgang Link Date: Mon, 24 Apr 2017 17:15:26 +0200 Subject: [PATCH] Include new storage function volume_send. If the storage backend support import and export we can send the contend to a remote host. --- PVE/Storage.pm | 18 ++++++++++++++ PVE/Storage/Plugin.pm | 8 ++++++ PVE/Storage/ZFSPlugin.pm | 7 ++++++ PVE/Storage/ZFSPoolPlugin.pm | 48 ++++++++++++++++++++++++++++++++++++ 4 files changed, 81 insertions(+) diff --git a/PVE/Storage.pm b/PVE/Storage.pm index 50c2f3f..4794818 100755 --- a/PVE/Storage.pm +++ b/PVE/Storage.pm @@ -216,6 +216,24 @@ sub volume_snapshot { } } +sub volume_send { + my ($cfg, $volid, $snap, $ip, $incremental_snap, $verbose, $limit, + $target_path) = @_; + + my ($storeid, $volname) = parse_volume_id($volid, 1); + if ($storeid) { + my $scfg = storage_config($cfg, $storeid); + my $plugin = PVE::Storage::Plugin->lookup($scfg->{type}); + return $plugin->volume_send($scfg, $storeid, $volname, $ip, $snap, + $incremental_snap, $verbose, $limit, $target_path); + + } elsif ($volid =~ m|^(/.+)$| && -e $volid) { + die "send file/device '$volid' is not possible\n"; + } else { + die "unable to parse volume ID '$volid'\n"; + } +} + sub volume_snapshot_rollback { my ($cfg, $volid, $snap) = @_; diff --git a/PVE/Storage/Plugin.pm b/PVE/Storage/Plugin.pm index 31b8541..d0df1f9 100644 --- a/PVE/Storage/Plugin.pm +++ b/PVE/Storage/Plugin.pm @@ -697,6 +697,14 @@ sub volume_snapshot { return undef; } +sub volume_send { + my ($class, $scfg, $storeid, $volname, $ip, $snap, + $incremental_snap, $verbose, $limit, $target_path) = @_; + + # implement in subclass + die "Volume_send is not implemented for $class"; +} + sub volume_rollback_is_possible { my ($class, $scfg, $storeid, $volname, $snap) = @_; diff --git a/PVE/Storage/ZFSPlugin.pm b/PVE/Storage/ZFSPlugin.pm index 9072205..9007193 100644 --- a/PVE/Storage/ZFSPlugin.pm +++ b/PVE/Storage/ZFSPlugin.pm @@ -336,6 +336,13 @@ sub volume_snapshot_rollback { $class->zfs_add_lun_mapping_entry($scfg, $volname); } +sub volume_send { + my ($class, $scfg, $storeid, $volname, $ip, $snap, + $incremental_snap, $verbose, $limit, $target_path) = @_; + + die "Volume_send is not implemented for ZFS over iSCSI.\n"; +} + sub volume_has_feature { my ($class, $scfg, $feature, $storeid, $volname, $snapname, $running) = @_; diff --git a/PVE/Storage/ZFSPoolPlugin.pm b/PVE/Storage/ZFSPoolPlugin.pm index ca0a2cf..5b98378 100644 --- a/PVE/Storage/ZFSPoolPlugin.pm +++ b/PVE/Storage/ZFSPoolPlugin.pm @@ -465,6 +465,54 @@ sub volume_snapshot { $class->zfs_request($scfg, undef, 'snapshot', "$scfg->{pool}/$vname\@$snap"); } +sub volume_send { + my ($class, $scfg, $storeid, $volname, $ip, $snap, + $incremental_snap, $verbose, $limit, $target_path) = @_; + + my ($vtype, $name, $vmid) = $class->parse_volname($volname); + + my $zpath = "$scfg->{pool}/$name"; + + die "$vtype is not allowed in ZFSPool!" if ($vtype ne "images"); + + my $cmdsend = []; + my $cmdlimit = []; + + push @$cmdsend, 'zfs', 'send', '-R'; + push @$cmdsend, '-v' if defined($verbose); + + if( defined($incremental_snap)) { + push @$cmdsend, '-I', "$zpath\@${incremental_snap}"; + } + + push @$cmdsend, '--', "$zpath\@${snap}"; + + # limit in kByte/s + if ($limit){ + my $bwl = $limit * 1024; + push @$cmdlimit, 'cstream', '-t', $bwl; + } + + my $cmdrecv = []; + + push @$cmdrecv, 'ssh', '-o', 'BatchMode=yes', "root\@${ip}", '--' if $ip; + push @$cmdrecv, 'zfs', 'recv', '-F', '--'; + + $zpath = $target_path if defined($target_path); + push @$cmdrecv, $zpath; + + + if ($limit) { + eval { run_command([$cmdsend, $cmdlimit, $cmdrecv]) }; + } else { + eval { run_command([$cmdsend, $cmdrecv]) }; + } + + if (my $err = $@) { + die $err; + } +} + sub volume_snapshot_delete { my ($class, $scfg, $storeid, $volname, $snap, $running) = @_; -- 2.39.2