[pve-devel] [PATCH pve-storage 4/4] Add support for creating LXC snapshot backup
Michael Rasmussen
mir at datanom.net
Wed Jun 14 21:55:11 CEST 2017
Signed-off-by: Michael Rasmussen <mir at datanom.net>
---
PVE/Storage/FreeNASPlugin.pm | 129 +++++++++++++++++++++++++------------------
1 file changed, 74 insertions(+), 55 deletions(-)
diff --git a/PVE/Storage/FreeNASPlugin.pm b/PVE/Storage/FreeNASPlugin.pm
index 0f2a56d..fee3d27 100644
--- a/PVE/Storage/FreeNASPlugin.pm
+++ b/PVE/Storage/FreeNASPlugin.pm
@@ -427,40 +427,38 @@ sub freenas_find_free_diskname {
}
sub freenas_get_lun_number {
- my ($scfg, $volname, $snap) = @_;
+ my ($scfg, $volname) = @_;
my $lunid = undef;
- if ($volname =~ /^(vm|base)-\d+-disk-(\d+)$/ && ! defined $snap) {
+ if ($volname =~ /^(vm|base)-\d+-disk-(\d+)$/) {
$lunid = $2 - 1;
} elsif ($volname =~ /^vm-(\d+)-state/) {
# Find id for temporary LUN
- if ($snap) {
- # TODO
- # Required to be able to exposed read-only LUNs for snapshot backup CT
- } else {
- my $target = freenas_get_target($scfg, $1);
- my $id = $max_luns;
- my $response = freenas_request($scfg, 'GET', "services/iscsi/targettoextent?limit=$limit");
- die HTTP::Status::status_message($response) if $response =~ /^\d+$/;
- my $t2extents = decode_json($response);
-
- foreach my $t2extent (@$t2extents) {
- next unless $t2extent->{iscsi_target} == $target &&
- $t2extent->{iscsi_lunid} + 1 > $max_luns &&
- $t2extent->{iscsi_lunid} < $max_luns + $active_snaps;
- my $eid = freenas_get_extent($scfg, $volname);
- if ($eid) {
- $response = freenas_request($scfg, 'GET', "services/iscsi/extent/$eid");
- die HTTP::Status::status_message($response) if $response =~ /^\d+$/;
- my $extent = decode_json($response);
- # Request to get lunid for an existing lun
- last if $t2extent->{iscsi_extent} eq $eid;
- }
- $id++;
+ my $target = freenas_get_target($scfg, $1);
+ my $id = $max_luns;
+ my $response = freenas_request($scfg, 'GET', "services/iscsi/targettoextent?limit=$limit");
+ die HTTP::Status::status_message($response) if $response =~ /^\d+$/;
+ my $t2extents = decode_json($response);
+
+ foreach my $t2extent (@$t2extents) {
+ next unless $t2extent->{iscsi_target} == $target &&
+ $t2extent->{iscsi_lunid} + 1 > $max_luns &&
+ $t2extent->{iscsi_lunid} < $max_luns + $active_snaps;
+ my $eid = freenas_get_extent($scfg, $volname);
+ if ($eid) {
+ $response = freenas_request($scfg, 'GET', "services/iscsi/extent/$eid");
+ die HTTP::Status::status_message($response) if $response =~ /^\d+$/;
+ my $extent = decode_json($response);
+ # Request to get lunid for an existing lun
+ last if $t2extent->{iscsi_extent} eq $eid;
}
- die "Max snapshots (4) is reached" unless ($id - $max_luns) < $active_snaps;
- $lunid = $id;
- }
+ $id++;
+ }
+ die "Max snapshots (4) is reached" unless ($id - $max_luns) < $active_snaps;
+ $lunid = $id;
+ } elsif ($volname =~ /^(vm|base)-\d+-disk-\d+\@vzdump$/) {
+ # Required to be able to exposed read-only LUNs for snapshot backup CT
+ $lunid = $max_luns + $active_snaps;
}
return $lunid;
@@ -891,12 +889,13 @@ sub list_images {
sub path {
my ($class, $scfg, $volname, $storeid, $snapname) = @_;
-
- die "direct access to snapshots not implemented"
- if defined($snapname);
+ #die "direct access to snapshots not implemented"
+ #if defined($snapname);
my ($vtype, $vname, $vmid) = $class->parse_volname($volname);
+ $vname = "$vname\@$snapname" if $snapname;
+
my $luns = get_active_luns($class, $storeid, $scfg, $vname);
my $path = disk_by_path($scfg, $vname);
@@ -1116,24 +1115,54 @@ sub volume_resize {
sub volume_snapshot {
my ($class, $scfg, $storeid, $volname, $snap) = @_;
-
- my $vname = ($class->parse_volname($volname))[1];
-
+
+ my (undef, $vname, $vmid) = $class->parse_volname($volname);
+
my $data = {
dataset => "$scfg->{pool}/$vname",
name => $snap,
};
- my $response = freenas_request($scfg, 'POST', "storage/snapshot", encode_json($data));
+ my $response = freenas_request($scfg, 'POST', "storage/snapshot/", encode_json($data));
die HTTP::Status::status_message($response) if $response =~ /^\d+$/;
+
+ if ($snap) {
+ eval {
+ freenas_create_lun($scfg, $vmid, "$vname\@$snap");
+ $class->activate_volume($storeid, $scfg, "$vname\@$snap");
+ };
+ if ($@) {
+ die "$@ - unable to activate snapshot from remote FreeNAS storage";
+ }
+ }
}
sub volume_snapshot_delete {
my ($class, $scfg, $storeid, $volname, $snap, $running) = @_;
- my $vname = ($class->parse_volname($volname))[1];
-
+ my (undef, $vname, $vmid) = $class->parse_volname($volname);
+
+ if ($snap) {
+ eval {
+ my $target = freenas_get_target($scfg, $vmid);
+ die "volume_snapshot_delete-> missing target" unless $target;
+ my $extent = freenas_get_extent($scfg, "$vname\@$snap");
+ die "volume_snapshot_delete-> missing extent" unless $extent;
+ my $tg2exent = freenas_get_target_to_exent($scfg, $extent, $target);
+ die "volume_snapshot_delete-> missing target to extent" unless $tg2exent;
+ my $lun = freenas_get_lun_number($scfg, "$vname\@$snap");
+ die "volume_snapshot_delete-> missing LUN" unless defined $lun;
+ freenas_delete_target_to_exent($scfg, $tg2exent);
+ freenas_delete_extent($scfg, $extent);
+ };
+ warn "$@ - unable to deactivate snapshot from remote FreeNAS storage" if $@;
+ }
+
my $response = freenas_request($scfg, 'DELETE', "storage/snapshot/$scfg->{pool}/$vname\@$snap");
die HTTP::Status::status_message($response) if $response =~ /^\d+$/;
+
+ if ($snap) {
+ $class->deactivate_volume($storeid, $scfg, "$vname\@$snap");
+ }
}
sub volume_snapshot_rollback {
@@ -1232,16 +1261,11 @@ sub deactivate_storage {
sub activate_volume {
my ($class, $storeid, $scfg, $volname, $snapname, $cache) = @_;
- # TODO: FreeNAS supports exposing a ro LUN from a snapshot
- # ERROR: Backup of VM xyz failed - unable to activate snapshot from remote zfs storage
- # at /usr/share/perl5/PVE/Storage/ZFSPlugin.pm line 418.
- # $vname\@$snapname
- die "mode failure - unable to activate snapshot from remote zfs storage" if $snapname;
-
- my (undef, $name) = $class->parse_volname($volname);
+ return if $snapname; # Activated when creating snapshot
+
+ my $name = ($class->parse_volname($volname))[1];
my $active_luns = get_active_luns($class, $storeid, $scfg, $name);
-
my $lun = freenas_get_lun_number($scfg, $name);
$active_luns->{$lun} = "0:0:0:$lun";
@@ -1266,18 +1290,13 @@ sub activate_volume {
# deactivate lun
sub deactivate_volume {
my ($class, $storeid, $scfg, $volname, $snapname, $cache) = @_;
-
- # TODO: FreeNAS supports exposing a ro LUN from a snapshot
- # ERROR: Backup of VM xyz failed - unable to activate snapshot from remote zfs storage
- # at /usr/share/perl5/PVE/Storage/ZFSPlugin.pm line 418.
- # $vname\@$snapname
- die "mode failure - unable to deactivate snapshot from remote zfs storage" if $snapname;
-
- my (undef, $name) = $class->parse_volname($volname);
+
+ return if $snapname; # Deactivated when deleting snapshot
+
+ my $name = ($class->parse_volname($volname))[1];
my $active_luns = get_active_luns($class, $storeid, $scfg, $name);
-
- my $lun = freenas_get_lun_number($scfg, $name);
+ my $lun = freenas_get_lun_number($scfg, $name);
delete $active_luns->{$lun};
eval {
--
2.1.4
----
This mail was virus scanned and spam checked before delivery.
This mail is also DKIM signed. See header dkim-signature.
More information about the pve-devel
mailing list