[pve-devel] [PATCH pve-storage 5/5] Fix regression and indentation
Michael Rasmussen
mir at datanom.net
Fri Jun 16 03:16:58 CEST 2017
snapshot backup of CT broke general snapshot handling.
Handle snapshot creation and deletion properly.
Signed-off-by: Michael Rasmussen <mir at datanom.net>
---
PVE/Storage/FreeNASPlugin.pm | 1570 +++++++++++++++++++++---------------------
1 file changed, 782 insertions(+), 788 deletions(-)
diff --git a/PVE/Storage/FreeNASPlugin.pm b/PVE/Storage/FreeNASPlugin.pm
index fee3d27..9fe64d6 100644
--- a/PVE/Storage/FreeNASPlugin.pm
+++ b/PVE/Storage/FreeNASPlugin.pm
@@ -58,7 +58,6 @@ sub freenas_request {
$req->authorization_basic($scfg->{username}, $scfg->{password});
my $res = $ua->request($req);
- #print Dumper($res);
return $res->code unless $res->is_success;
return $res->content;
@@ -66,43 +65,43 @@ sub freenas_request {
sub freenas_get_version {
my ($scfg) = @_;
-
- my $response = freenas_request($scfg, 'GET', "system/version");
- die HTTP::Status::status_message($response) if $response =~ /^\d+$/;
- my $info = decode_json($response);
- $fullversion = $info->{fullversion};
- if ($fullversion =~ /^\w+-(\d+)\.(\d*)\.(\d*)/) {
- my $minor = $2;
- my $micro = $3;
-
- if ($minor) {
- $minor = "0$minor" unless $minor > 9;
- } else {
- $minor = '00';
- }
-
- if ($micro) {
- $micro = "0$micro" unless $micro > 9;
- } else {
- $micro = '00';
- }
-
- $version = "$1$minor$micro";
- } else {
- $version = '90200';
- }
+
+ my $response = freenas_request($scfg, 'GET', "system/version");
+ die HTTP::Status::status_message($response) if $response =~ /^\d+$/;
+ my $info = decode_json($response);
+ $fullversion = $info->{fullversion};
+ if ($fullversion =~ /^\w+-(\d+)\.(\d*)\.(\d*)/) {
+ my $minor = $2;
+ my $micro = $3;
+
+ if ($minor) {
+ $minor = "0$minor" unless $minor > 9;
+ } else {
+ $minor = '00';
+ }
+
+ if ($micro) {
+ $micro = "0$micro" unless $micro > 9;
+ } else {
+ $micro = '00';
+ }
+
+ $version = "$1$minor$micro";
+ } else {
+ $version = '90200';
+ }
}
sub freenas_list_zvol {
my ($scfg) = @_;
- freenas_get_version($scfg) unless $version;
-
- my $response = freenas_request($scfg, 'GET', "storage/volume/$scfg->{pool}/zvols?limit=$limit");
- die HTTP::Status::status_message($response) if $response =~ /^\d+$/;
+ freenas_get_version($scfg) unless $version;
+
+ my $response = freenas_request($scfg, 'GET', "storage/volume/$scfg->{pool}/zvols?limit=$limit");
+ die HTTP::Status::status_message($response) if $response =~ /^\d+$/;
my $zvols = decode_json($response);
- $response = freenas_request($scfg, 'GET', "storage/snapshot?limit=$limit");
- die HTTP::Status::status_message($response) if $response =~ /^\d+$/;
+ $response = freenas_request($scfg, 'GET', "storage/snapshot?limit=$limit");
+ die HTTP::Status::status_message($response) if $response =~ /^\d+$/;
my $snapshots = decode_json($response);
my $list = ();
@@ -110,13 +109,13 @@ sub freenas_list_zvol {
my $vmid;
my $parent;
foreach my $zvol (@$zvols) {
- next unless $zvol->{name} =~ /^(base|vm)-(\d+)-disk-\d+$/;
- $vmid = $2;
- $parent = undef;
- foreach my $snap (@$snapshots) {
- next unless $snap->{name} eq "__base__$vmid";
- $parent = $snap->{filesystem} =~ /^$scfg->{pool}\/(.+)$/ ? $1 : undef;
- }
+ next unless $zvol->{name} =~ /^(base|vm)-(\d+)-disk-\d+$/;
+ $vmid = $2;
+ $parent = undef;
+ foreach my $snap (@$snapshots) {
+ next unless $snap->{name} eq "__base__$vmid";
+ $parent = $snap->{filesystem} =~ /^$scfg->{pool}\/(.+)$/ ? $1 : undef;
+ }
$list->{$scfg->{pool}}->{$zvol->{name}} = {
name => $zvol->{name},
size => $zvol->{volsize},
@@ -125,280 +124,280 @@ sub freenas_list_zvol {
format => 'raw',
};
if ($zvol->{name} =~ /^base-(.*)/) {
- $hide->{"vm-$1"} = 1;
+ $hide->{"vm-$1"} = 1;
}
}
delete @{$list->{$scfg->{pool}}}{keys %$hide};
-
+
return $list;
}
sub freenas_no_more_extents {
- my ($scfg, $target) = @_;
-
- my $response = freenas_request($scfg, 'GET', "services/iscsi/targettoextent?limit=$limit");
- die HTTP::Status::status_message($response) if $response =~ /^\d+$/;
- my $extents = decode_json($response);
- foreach my $extent (@$extents) {
- return 0 if $extent->{iscsi_target} == $target;
- }
-
- return 1;
+ my ($scfg, $target) = @_;
+
+ my $response = freenas_request($scfg, 'GET', "services/iscsi/targettoextent?limit=$limit");
+ die HTTP::Status::status_message($response) if $response =~ /^\d+$/;
+ my $extents = decode_json($response);
+ foreach my $extent (@$extents) {
+ return 0 if $extent->{iscsi_target} == $target;
+ }
+
+ return 1;
}
-
+
sub freenas_get_target {
- my ($scfg, $vmid) = @_;
- my $target = undef;
-
- my $response = freenas_request($scfg, 'GET', "services/iscsi/target?limit=$limit");
- die HTTP::Status::status_message($response) if $response =~ /^\d+$/;
- my $targets = decode_json($response);
- foreach my $t (@$targets) {
- if ($t->{iscsi_target_name} eq "vm-$vmid") {
- $target = $t->{id};
- last;
- }
- }
-
- return $target;
+ my ($scfg, $vmid) = @_;
+ my $target = undef;
+
+ my $response = freenas_request($scfg, 'GET', "services/iscsi/target?limit=$limit");
+ die HTTP::Status::status_message($response) if $response =~ /^\d+$/;
+ my $targets = decode_json($response);
+ foreach my $t (@$targets) {
+ if ($t->{iscsi_target_name} eq "vm-$vmid") {
+ $target = $t->{id};
+ last;
+ }
+ }
+
+ return $target;
}
sub freenas_create_target {
- my ($scfg, $vmid, $valid_code) = @_;
- my $data;
-
- freenas_get_version($scfg) unless $version;
-
- if ($version < 110000) {
- $data = {
- iscsi_target_alias => "vm-$vmid",
- iscsi_target_name => "vm-$vmid",
- };
- } elsif ($version < 110100) {
- $data = {
- iscsi_target_alias => "vm-$vmid",
- iscsi_target_name => "vm-$vmid",
- };
- } else {
- die "FreeNAS-$version: Unsupported!";
- }
- my $response = freenas_request($scfg, 'POST', "services/iscsi/target", encode_json($data), $valid_code);
- if ($response =~ /^\d+$/) {
- return freenas_get_target($scfg, $vmid) if $valid_code && $response == $valid_code;
- die HTTP::Status::status_message($response);
- }
- my $target = decode_json($response);
-
- die "Creating target for 'vm-$vmid' failed" unless $target->{id};
-
- return $target->{id};
+ my ($scfg, $vmid, $valid_code) = @_;
+ my $data;
+
+ freenas_get_version($scfg) unless $version;
+
+ if ($version < 110000) {
+ $data = {
+ iscsi_target_alias => "vm-$vmid",
+ iscsi_target_name => "vm-$vmid",
+ };
+ } elsif ($version < 110100) {
+ $data = {
+ iscsi_target_alias => "vm-$vmid",
+ iscsi_target_name => "vm-$vmid",
+ };
+ } else {
+ die "FreeNAS-$version: Unsupported!";
+ }
+ my $response = freenas_request($scfg, 'POST', "services/iscsi/target", encode_json($data), $valid_code);
+ if ($response =~ /^\d+$/) {
+ return freenas_get_target($scfg, $vmid) if $valid_code && $response == $valid_code;
+ die HTTP::Status::status_message($response);
+ }
+ my $target = decode_json($response);
+
+ die "Creating target for 'vm-$vmid' failed" unless $target->{id};
+
+ return $target->{id};
}
sub freenas_delete_target {
- my ($scfg, $target) = @_;
+ my ($scfg, $target) = @_;
- my $response = freenas_request($scfg, 'DELETE', "services/iscsi/target/$target");
- die HTTP::Status::status_message($response) if $response =~ /^\d+$/;
+ my $response = freenas_request($scfg, 'DELETE', "services/iscsi/target/$target");
+ die HTTP::Status::status_message($response) if $response =~ /^\d+$/;
}
sub freenas_get_target_name {
- my ($scfg, $volname) = @_;
- my $name = undef;
-
- if ($volname =~ /^(vm|base)-(\d+)-/) {
- $name = "vm-$2";
- return "$target_prefix\:$name";
- }
-
- return undef;
+ my ($scfg, $volname) = @_;
+ my $name = undef;
+
+ if ($volname =~ /^(vm|base)-(\d+)-/) {
+ $name = "vm-$2";
+ return "$target_prefix\:$name";
+ }
+
+ return undef;
}
sub freenas_create_target_group {
- my ($scfg, $target, $valid_code) = @_;
- my $data;
-
- freenas_get_version($scfg) unless $version;
-
- # Trying to create a target group which already exists will cause and internal
- # server error so if creating an existing target group should be allowed (return
- # existing target group number we must search prior to create
- if ($valid_code && $valid_code == 409) {
- my $tg = freenas_get_target_group($scfg, $target);
- return $tg if $tg;
- }
-
- if ($version < 110000) {
- $data = {
- iscsi_target => $target,
- iscsi_target_authgroup => $scfg->{auth_group} ? $scfg->{auth_group} : undef,
- iscsi_target_portalgroup => $scfg->{portal_group},
- iscsi_target_initiatorgroup => $scfg->{initiator_group},
- iscsi_target_authtype => $scfg->{auth_type} ? $scfg->{auth_type} : 'None',
- iscsi_target_initialdigest => "Auto",
- };
- } elsif ($version < 110100) {
- $data = {
- iscsi_target => $target,
- iscsi_target_authgroup => $scfg->{auth_group} ? $scfg->{auth_group} : undef,
- iscsi_target_portalgroup => $scfg->{portal_group},
- iscsi_target_initiatorgroup => $scfg->{initiator_group},
- iscsi_target_authtype => $scfg->{auth_type} ? $scfg->{auth_type} : 'None',
- iscsi_target_initialdigest => "Auto",
- };
- } else {
- die "FreeNAS-$version: Unsupported!";
- }
-
- my $response = freenas_request($scfg, 'POST', "services/iscsi/targetgroup", encode_json($data), $valid_code);
- if ($response =~ /^\d+$/) {
- if ($valid_code != 409) {
- return freenas_get_target_group($scfg, $target) if $valid_code && $response == $valid_code;
- }
- die HTTP::Status::status_message($response);
- }
- my $tg = decode_json($response);
-
- die "Creating target group for target '$target' failed" unless $tg->{id};
-
- return $tg->{id};
+ my ($scfg, $target, $valid_code) = @_;
+ my $data;
+
+ freenas_get_version($scfg) unless $version;
+
+ # Trying to create a target group which already exists will cause and internal
+ # server error so if creating an existing target group should be allowed (return
+ # existing target group number we must search prior to create
+ if ($valid_code && $valid_code == 409) {
+ my $tg = freenas_get_target_group($scfg, $target);
+ return $tg if $tg;
+ }
+
+ if ($version < 110000) {
+ $data = {
+ iscsi_target => $target,
+ iscsi_target_authgroup => $scfg->{auth_group} ? $scfg->{auth_group} : undef,
+ iscsi_target_portalgroup => $scfg->{portal_group},
+ iscsi_target_initiatorgroup => $scfg->{initiator_group},
+ iscsi_target_authtype => $scfg->{auth_type} ? $scfg->{auth_type} : 'None',
+ iscsi_target_initialdigest => "Auto",
+ };
+ } elsif ($version < 110100) {
+ $data = {
+ iscsi_target => $target,
+ iscsi_target_authgroup => $scfg->{auth_group} ? $scfg->{auth_group} : undef,
+ iscsi_target_portalgroup => $scfg->{portal_group},
+ iscsi_target_initiatorgroup => $scfg->{initiator_group},
+ iscsi_target_authtype => $scfg->{auth_type} ? $scfg->{auth_type} : 'None',
+ iscsi_target_initialdigest => "Auto",
+ };
+ } else {
+ die "FreeNAS-$version: Unsupported!";
+ }
+
+ my $response = freenas_request($scfg, 'POST', "services/iscsi/targetgroup", encode_json($data), $valid_code);
+ if ($response =~ /^\d+$/) {
+ if ($valid_code != 409) {
+ return freenas_get_target_group($scfg, $target) if $valid_code && $response == $valid_code;
+ }
+ die HTTP::Status::status_message($response);
+ }
+ my $tg = decode_json($response);
+
+ die "Creating target group for target '$target' failed" unless $tg->{id};
+
+ return $tg->{id};
}
sub freenas_delete_target_group {
- my ($scfg, $tg) = @_;
+ my ($scfg, $tg) = @_;
- my $response = freenas_request($scfg, 'DELETE', "services/iscsi/targetgroup/$tg");
- die HTTP::Status::status_message($response) if $response =~ /^\d+$/;
+ my $response = freenas_request($scfg, 'DELETE', "services/iscsi/targetgroup/$tg");
+ die HTTP::Status::status_message($response) if $response =~ /^\d+$/;
}
sub freenas_get_target_group {
- my ($scfg, $target) = @_;
- my $targetgroup = undef;
-
- my $response = freenas_request($scfg, 'GET', "services/iscsi/targetgroup?limit=$limit");
- die HTTP::Status::status_message($response) if $response =~ /^\d+$/;
- my $targetgroups = decode_json($response);
-
- foreach my $tgroup (@$targetgroups) {
- if ($tgroup->{iscsi_target} == $target &&
- $tgroup->{iscsi_target_portalgroup} == $scfg->{portal_group} &&
- $tgroup->{iscsi_target_initiatorgroup} == $scfg->{initiator_group}) {
- $targetgroup = $tgroup->{id};
- last;
- }
- }
-
- return $targetgroup;
+ my ($scfg, $target) = @_;
+ my $targetgroup = undef;
+
+ my $response = freenas_request($scfg, 'GET', "services/iscsi/targetgroup?limit=$limit");
+ die HTTP::Status::status_message($response) if $response =~ /^\d+$/;
+ my $targetgroups = decode_json($response);
+
+ foreach my $tgroup (@$targetgroups) {
+ if ($tgroup->{iscsi_target} == $target &&
+ $tgroup->{iscsi_target_portalgroup} == $scfg->{portal_group} &&
+ $tgroup->{iscsi_target_initiatorgroup} == $scfg->{initiator_group}) {
+ $targetgroup = $tgroup->{id};
+ last;
+ }
+ }
+
+ return $targetgroup;
}
sub freenas_create_extent {
- my ($scfg, $zvol) = @_;
- my $data;
-
- freenas_get_version($scfg) unless $version;
-
- if ($version < 110000) {
- $data = {
- iscsi_target_extent_type => 'Disk',
- iscsi_target_extent_name => $zvol,
- iscsi_target_extent_disk => "zvol/$scfg->{pool}/$zvol",
- };
- } elsif ($version < 110100) {
- $data = {
- iscsi_target_extent_type => 'Disk',
- iscsi_target_extent_name => $zvol,
- iscsi_target_extent_disk => "zvol/$scfg->{pool}/$zvol",
- };
- } else {
- die "FreeNAS-$version: Unsupported!";
- }
-
- my $response = freenas_request($scfg, 'POST', "services/iscsi/extent", encode_json($data));
- die HTTP::Status::status_message($response) if ($response =~ /^\d+$/);
- my $extent = decode_json($response);
-
- die "Creating LUN for volume '$zvol' failed" unless $extent->{id};
-
- return $extent->{id};
+ my ($scfg, $zvol) = @_;
+ my $data;
+
+ freenas_get_version($scfg) unless $version;
+
+ if ($version < 110000) {
+ $data = {
+ iscsi_target_extent_type => 'Disk',
+ iscsi_target_extent_name => $zvol,
+ iscsi_target_extent_disk => "zvol/$scfg->{pool}/$zvol",
+ };
+ } elsif ($version < 110100) {
+ $data = {
+ iscsi_target_extent_type => 'Disk',
+ iscsi_target_extent_name => $zvol,
+ iscsi_target_extent_disk => "zvol/$scfg->{pool}/$zvol",
+ };
+ } else {
+ die "FreeNAS-$version: Unsupported!";
+ }
+
+ my $response = freenas_request($scfg, 'POST', "services/iscsi/extent", encode_json($data));
+ die HTTP::Status::status_message($response) if ($response =~ /^\d+$/);
+ my $extent = decode_json($response);
+
+ die "Creating LUN for volume '$zvol' failed" unless $extent->{id};
+
+ return $extent->{id};
}
sub freenas_delete_extent {
- my ($scfg, $extent) = @_;
+ my ($scfg, $extent) = @_;
- my $response = freenas_request($scfg, 'DELETE', "services/iscsi/extent/$extent");
- die HTTP::Status::status_message($response) if $response =~ /^\d+$/;
+ my $response = freenas_request($scfg, 'DELETE', "services/iscsi/extent/$extent");
+ die HTTP::Status::status_message($response) if $response =~ /^\d+$/;
}
sub freenas_get_extent {
- my ($scfg, $volname) = @_;
- my $extent = undef;
-
- my $response = freenas_request($scfg, 'GET', "services/iscsi/extent?limit=$limit");
- die HTTP::Status::status_message($response) if $response =~ /^\d+$/;
- my $extents = decode_json($response);
- foreach my $ext (@$extents) {
- if ($ext->{iscsi_target_extent_path} =~ /$scfg->{pool}\/$volname$/) {
- $extent = $ext->{id};
- last;
- }
- }
-
- return $extent;
+ my ($scfg, $volname) = @_;
+ my $extent = undef;
+
+ my $response = freenas_request($scfg, 'GET', "services/iscsi/extent?limit=$limit");
+ die HTTP::Status::status_message($response) if $response =~ /^\d+$/;
+ my $extents = decode_json($response);
+ foreach my $ext (@$extents) {
+ if ($ext->{iscsi_target_extent_path} =~ /$scfg->{pool}\/$volname$/) {
+ $extent = $ext->{id};
+ last;
+ }
+ }
+
+ return $extent;
}
sub freenas_create_target_to_exent {
- my ($scfg, $target, $extent, $lunid) = @_;
- my $data;
-
- freenas_get_version($scfg) unless $version;
-
- if ($version < 110000) {
- $data = {
- iscsi_target => $target,
- iscsi_extent => $extent,
- iscsi_lunid => $lunid,
- };
- } elsif ($version < 110100) {
- $data = {
- iscsi_target => $target,
- iscsi_extent => $extent,
- iscsi_lunid => $lunid,
- };
- } else {
- die "FreeNAS-$version: Unsupported!";
- }
-
- my $response = freenas_request($scfg, 'POST', "services/iscsi/targettoextent", encode_json($data));
- die HTTP::Status::status_message($response) if ($response =~ /^\d+$/);
- my $tg2extent = decode_json($response);
-
- die "Creating view for LUN '$extent' failed" unless $tg2extent->{id};
-
- return $tg2extent->{id};
+ my ($scfg, $target, $extent, $lunid) = @_;
+ my $data;
+
+ freenas_get_version($scfg) unless $version;
+
+ if ($version < 110000) {
+ $data = {
+ iscsi_target => $target,
+ iscsi_extent => $extent,
+ iscsi_lunid => $lunid,
+ };
+ } elsif ($version < 110100) {
+ $data = {
+ iscsi_target => $target,
+ iscsi_extent => $extent,
+ iscsi_lunid => $lunid,
+ };
+ } else {
+ die "FreeNAS-$version: Unsupported!";
+ }
+
+ my $response = freenas_request($scfg, 'POST', "services/iscsi/targettoextent", encode_json($data));
+ die HTTP::Status::status_message($response) if ($response =~ /^\d+$/);
+ my $tg2extent = decode_json($response);
+
+ die "Creating view for LUN '$extent' failed" unless $tg2extent->{id};
+
+ return $tg2extent->{id};
}
sub freenas_delete_target_to_exent {
- my ($scfg, $tg2exent) = @_;
+ my ($scfg, $tg2exent) = @_;
- my $response = freenas_request($scfg, 'DELETE', "services/iscsi/targettoextent/$tg2exent");
- die HTTP::Status::status_message($response) if $response =~ /^\d+$/;
+ my $response = freenas_request($scfg, 'DELETE', "services/iscsi/targettoextent/$tg2exent");
+ die HTTP::Status::status_message($response) if $response =~ /^\d+$/;
}
sub freenas_get_target_to_exent {
- my ($scfg, $extent, $target) = @_;
- my $t2extent = undef;
-
- 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 $t2ext (@$t2extents) {
- if ($t2ext->{iscsi_target} == $target && $t2ext->{iscsi_extent} == $extent) {
- $t2extent = $t2ext->{id};
- last;
- }
- }
-
- return $t2extent;
+ my ($scfg, $extent, $target) = @_;
+ my $t2extent = undef;
+
+ 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 $t2ext (@$t2extents) {
+ if ($t2ext->{iscsi_target} == $target && $t2ext->{iscsi_extent} == $extent) {
+ $t2extent = $t2ext->{id};
+ last;
+ }
+ }
+
+ return $t2extent;
}
sub freenas_find_free_diskname {
@@ -410,20 +409,20 @@ sub freenas_find_free_diskname {
my $disk_ids = {};
my $dat = $volumes->{$scfg->{pool}};
- foreach my $image (keys %$dat) {
- my $volname = $dat->{$image}->{name};
- if ($volname =~ m/(vm|base)-$vmid-disk-(\d+)/){
- $disk_ids->{$2} = 1;
- }
- }
-
- for (my $i = 1; $i < $max_luns + 1; $i++) {
- if (!$disk_ids->{$i}) {
- return "vm-$vmid-disk-$i";
- }
- }
-
- die "Maximum number of LUNs($max_luns) for this VM $vmid in storage '$storeid' is reached.";
+ foreach my $image (keys %$dat) {
+ my $volname = $dat->{$image}->{name};
+ if ($volname =~ m/(vm|base)-$vmid-disk-(\d+)/){
+ $disk_ids->{$2} = 1;
+ }
+ }
+
+ for (my $i = 1; $i < $max_luns + 1; $i++) {
+ if (!$disk_ids->{$i}) {
+ return "vm-$vmid-disk-$i";
+ }
+ }
+
+ die "Maximum number of LUNs($max_luns) for this VM $vmid in storage '$storeid' is reached.";
}
sub freenas_get_lun_number {
@@ -431,31 +430,31 @@ sub freenas_get_lun_number {
my $lunid = undef;
if ($volname =~ /^(vm|base)-\d+-disk-(\d+)$/) {
- $lunid = $2 - 1;
+ $lunid = $2 - 1;
} elsif ($volname =~ /^vm-(\d+)-state/) {
- # Find id for temporary LUN
- 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++;
- }
- die "Max snapshots (4) is reached" unless ($id - $max_luns) < $active_snaps;
- $lunid = $id;
+ # Find id for temporary LUN
+ 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++;
+ }
+ 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;
@@ -465,67 +464,67 @@ sub freenas_get_lun_number {
}
sub freenas_create_lun {
- my ($scfg, $vmid, $zvol) = @_;
- my ($target, $tg, $extent, $tg2exent) = (undef, undef, undef, undef);
-
- eval {
- $target = freenas_create_target($scfg, $vmid, 409);
- die "create_lun-> Could not create target for VM '$vmid'" unless $target;
- $tg = freenas_create_target_group($scfg, $target, 409);
- die "create_lun-> Could not create target group for VM '$vmid'" unless $tg;
- $extent = freenas_create_extent($scfg, $zvol);
- die "create_lun-> Could not create extent for VM '$vmid'" unless $extent;
- my $lunid = freenas_get_lun_number($scfg, $zvol);
- die "create_lun-> $zvol: Bad name format for VM '$vmid'" unless defined $lunid;
- $tg2exent = freenas_create_target_to_exent($scfg, $target, $extent, $lunid);
- die "create_lun-> Could not create target to extend for VM '$vmid'" unless defined $tg2exent;
- };
- if ($@) {
- my $err = $@;
- if ($tg2exent) {
- freenas_delete_target_to_exent($scfg, $tg2exent);
- }
- if ($extent) {
- freenas_delete_extent($scfg, $extent);
- }
- if ($target && freenas_no_more_extents($scfg, $target)) {
- if ($tg) {
- freenas_delete_target_group($scfg, $tg);
- }
- freenas_delete_target($scfg, $target);
- }
- die $err;
- }
+ my ($scfg, $vmid, $zvol) = @_;
+ my ($target, $tg, $extent, $tg2exent) = (undef, undef, undef, undef);
+
+ eval {
+ $target = freenas_create_target($scfg, $vmid, 409);
+ die "create_lun-> Could not create target for VM '$vmid'" unless $target;
+ $tg = freenas_create_target_group($scfg, $target, 409);
+ die "create_lun-> Could not create target group for VM '$vmid'" unless $tg;
+ $extent = freenas_create_extent($scfg, $zvol);
+ die "create_lun-> Could not create extent for VM '$vmid'" unless $extent;
+ my $lunid = freenas_get_lun_number($scfg, $zvol);
+ die "create_lun-> $zvol: Bad name format for VM '$vmid'" unless defined $lunid;
+ $tg2exent = freenas_create_target_to_exent($scfg, $target, $extent, $lunid);
+ die "create_lun-> Could not create target to extend for VM '$vmid'" unless defined $tg2exent;
+ };
+ if ($@) {
+ my $err = $@;
+ if ($tg2exent) {
+ freenas_delete_target_to_exent($scfg, $tg2exent);
+ }
+ if ($extent) {
+ freenas_delete_extent($scfg, $extent);
+ }
+ if ($target && freenas_no_more_extents($scfg, $target)) {
+ if ($tg) {
+ freenas_delete_target_group($scfg, $tg);
+ }
+ freenas_delete_target($scfg, $target);
+ }
+ die $err;
+ }
}
sub freenas_create_zvol {
- my ($scfg, $volname, $size) = @_;
-
- my $data = {
- name => $volname,
- volsize => $size,
- };
- my $response = freenas_request($scfg, 'POST', "storage/volume/$scfg->{pool}/zvols", encode_json($data));
- die HTTP::Status::status_message($response) if ($response =~ /^\d+$/);
- my $zvol = decode_json($response);
-
- die "$volname: Failed creating volume" unless $zvol && $zvol->{name};
-
- return $zvol->{name};
+ my ($scfg, $volname, $size) = @_;
+
+ my $data = {
+ name => $volname,
+ volsize => $size,
+ };
+ my $response = freenas_request($scfg, 'POST', "storage/volume/$scfg->{pool}/zvols", encode_json($data));
+ die HTTP::Status::status_message($response) if ($response =~ /^\d+$/);
+ my $zvol = decode_json($response);
+
+ die "$volname: Failed creating volume" unless $zvol && $zvol->{name};
+
+ return $zvol->{name};
}
sub freenas_delete_zvol {
- my ($scfg, $volname) = @_;
+ my ($scfg, $volname) = @_;
- my $response = freenas_request($scfg, 'DELETE', "storage/volume/$scfg->{pool}/zvols/$volname");
- die HTTP::Status::status_message($response) if $response =~ /^\d+$/;
+ my $response = freenas_request($scfg, 'DELETE', "storage/volume/$scfg->{pool}/zvols/$volname");
+ die HTTP::Status::status_message($response) if $response =~ /^\d+$/;
}
sub os_request {
- my ($cmd, $noerr, $timeout) = @_;
+ my ($cmd, $noerr, $timeout) = @_;
- $timeout = PVE::RPCEnvironment::is_worker() ? 60*60 : 5 if !$timeout;
- $noerr = 0 if !$noerr;
+ $timeout = PVE::RPCEnvironment::is_worker() ? 60*60 : 5 if !$timeout;
+ $noerr = 0 if !$noerr;
my $text = '';
@@ -534,200 +533,200 @@ sub os_request {
$text .= "$line\n";
};
- my $exit_code = run_command($cmd, noerr => $noerr, errfunc => $output, outfunc => $output, timeout => $timeout);
+ my $exit_code = run_command($cmd, noerr => $noerr, errfunc => $output, outfunc => $output, timeout => $timeout);
return wantarray ? ($exit_code, $text) : $exit_code;
}
sub bail_out {
- my ($class, $storeid, $scfg, $volname, $err) = @_;
-
- $class->free_image($storeid, $scfg, $volname);
- die $err;
+ my ($class, $storeid, $scfg, $volname, $err) = @_;
+
+ $class->free_image($storeid, $scfg, $volname);
+ die $err;
}
sub disk_by_path {
- my ($scfg, $volname) = @_;
+ my ($scfg, $volname) = @_;
- my $target = freenas_get_target_name($scfg, $volname);
- my $lun = freenas_get_lun_number($scfg, $volname);
- my $path = "/dev/disk/by-path/ip-$scfg->{portal}\:3260-iscsi-$target-lun-$lun";
+ my $target = freenas_get_target_name($scfg, $volname);
+ my $lun = freenas_get_lun_number($scfg, $volname);
+ my $path = "/dev/disk/by-path/ip-$scfg->{portal}\:3260-iscsi-$target-lun-$lun";
- return $path;
+ return $path;
}
sub build_lun_list {
- my ($scfg, $sid, $lun) = @_;
-
- my $luns = {};
- my $text = '';
- my $exit = 0;
-
- eval {
- ($exit, $text) = os_request("iscsiadm -m session -r $sid -P3", 1, 60);
- };
- if ($@) {
- # An exist code of 22 means no active session otherwise an error
- if ($exit != 22) {
- die "$@";
- }
- }
- if ($text =~ /.*Host Number:\s*(\d+)\s+State:\s+running(.*)/s) {
- my $host = $1;
- my $found = 0;
- for (split /^/, $2) {
- if ($_ =~ /Channel\s+(\d+)\s+Id\s+(\d+)\s+Lun:\s+(\d+)/) {
- if (defined $lun && $lun == $3) {
- $luns = {};
- $found = 1;
- }
- $luns->{$3} = "$host:".int($1).":$2:$3";
- last if $found;
- }
- }
- }
-
- return $luns;
+ my ($scfg, $sid, $lun) = @_;
+
+ my $luns = {};
+ my $text = '';
+ my $exit = 0;
+
+ eval {
+ ($exit, $text) = os_request("iscsiadm -m session -r $sid -P3", 1, 60);
+ };
+ if ($@) {
+ # An exist code of 22 means no active session otherwise an error
+ if ($exit != 22) {
+ die "$@";
+ }
+ }
+ if ($text =~ /.*Host Number:\s*(\d+)\s+State:\s+running(.*)/s) {
+ my $host = $1;
+ my $found = 0;
+ for (split /^/, $2) {
+ if ($_ =~ /Channel\s+(\d+)\s+Id\s+(\d+)\s+Lun:\s+(\d+)/) {
+ if (defined $lun && $lun == $3) {
+ $luns = {};
+ $found = 1;
+ }
+ $luns->{$3} = "$host:".int($1).":$2:$3";
+ last if $found;
+ }
+ }
+ }
+
+ return $luns;
}
sub get_sid {
- my ($scfg, $volname) = @_;
- my $sid = -1;
- my $text = '';
- my $exit = 0;
-
- my $target = freenas_get_target_name($scfg, $volname);
-
- eval {
- ($exit, $text) = os_request("iscsiadm -m node -T $target -p $scfg->{portal} -s", 1, 60);
- };
- if ($@) {
- # An exist code of 21 or 22 means no active session otherwise an error
- if ($exit != 21 || $exit != 22) {
- die "$@";
- }
- }
- if ($text =~ /.*\[sid\:\s*(\d+),\s*.*/) {
- $sid = $1;
- }
-
- return $sid;
+ my ($scfg, $volname) = @_;
+ my $sid = -1;
+ my $text = '';
+ my $exit = 0;
+
+ my $target = freenas_get_target_name($scfg, $volname);
+
+ eval {
+ ($exit, $text) = os_request("iscsiadm -m node -T $target -p $scfg->{portal} -s", 1, 60);
+ };
+ if ($@) {
+ # An exist code of 21 or 22 means no active session otherwise an error
+ if ($exit != 21 || $exit != 22) {
+ die "$@";
+ }
+ }
+ if ($text =~ /.*\[sid\:\s*(\d+),\s*.*/) {
+ $sid = $1;
+ }
+
+ return $sid;
}
sub create_session {
- my ($scfg, $volname) = @_;
- my $sid = -1;
- my $exit = undef;
-
- my $target = freenas_get_target_name($scfg, $volname);
-
- eval {
- $exit = os_request("iscsiadm -m node -T $target -p $scfg->{portal} --login", 1, 60);
- if ($exit == 21) {
- eval {
- os_request("iscsiadm -m discovery -t sendtargets -p $scfg->{portal}", 0, 60);
- os_request("iscsiadm -m node -T $target -p $scfg->{portal} --login", 0, 60);
- };
- }
- };
- if ($@) {
- if ($exit == 21) {
- eval {
- os_request("iscsiadm -m discovery -t sendtargets -p $scfg->{portal}", 0, 60);
- os_request("iscsiadm -m node -T $target -p $scfg->{portal} --login", 0, 60);
- };
- } else {
- die $@;
- }
- }
- eval {
- $sid = get_sid($scfg, $volname);
- };
- die "$@" if $@;
- die "Could not create session" if $sid < 0;
-
- return $sid;
+ my ($scfg, $volname) = @_;
+ my $sid = -1;
+ my $exit = undef;
+
+ my $target = freenas_get_target_name($scfg, $volname);
+
+ eval {
+ $exit = os_request("iscsiadm -m node -T $target -p $scfg->{portal} --login", 1, 60);
+ if ($exit == 21) {
+ eval {
+ os_request("iscsiadm -m discovery -t sendtargets -p $scfg->{portal}", 0, 60);
+ os_request("iscsiadm -m node -T $target -p $scfg->{portal} --login", 0, 60);
+ };
+ }
+ };
+ if ($@) {
+ if ($exit == 21) {
+ eval {
+ os_request("iscsiadm -m discovery -t sendtargets -p $scfg->{portal}", 0, 60);
+ os_request("iscsiadm -m node -T $target -p $scfg->{portal} --login", 0, 60);
+ };
+ } else {
+ die $@;
+ }
+ }
+ eval {
+ $sid = get_sid($scfg, $volname);
+ };
+ die "$@" if $@;
+ die "Could not create session" if $sid < 0;
+
+ return $sid;
}
sub delete_session {
- my ($scfg, $sid) = @_;
-
- eval {
- os_request("iscsiadm -m session -r $sid --logout", 0, 60);
- };
+ my ($scfg, $sid) = @_;
+
+ eval {
+ os_request("iscsiadm -m session -r $sid --logout", 0, 60);
+ };
}
sub remove_local_lun {
- my ($id) = @_;
-
- os_request("echo 1 > /sys/bus/scsi/devices/$id/delete", 0, 60);
+ my ($id) = @_;
+
+ os_request("echo 1 > /sys/bus/scsi/devices/$id/delete", 0, 60);
}
sub deactivate_luns {
- # $luns contains a hash of luns to keep
- my ($scfg, $volname, $luns) = @_;
-
- $luns = {} if !$luns;
- my $sid;
- my $list = {};
-
- eval {
- $sid = get_sid($scfg, $volname);
- };
- die "$@" if $@;
-
- eval {
- $list = build_lun_list($scfg, $sid);
-
- foreach my $key (keys %$list) {
- next if exists($luns->{$key});
- remove_local_lun($list->{$key});
- }
- };
- die "$@" if $@;
+ # $luns contains a hash of luns to keep
+ my ($scfg, $volname, $luns) = @_;
+
+ $luns = {} if !$luns;
+ my $sid;
+ my $list = {};
+
+ eval {
+ $sid = get_sid($scfg, $volname);
+ };
+ die "$@" if $@;
+
+ eval {
+ $list = build_lun_list($scfg, $sid);
+
+ foreach my $key (keys %$list) {
+ next if exists($luns->{$key});
+ remove_local_lun($list->{$key});
+ }
+ };
+ die "$@" if $@;
}
sub get_active_luns {
- my ($class, $storeid, $scfg, $volname) = @_;
-
- my $sid = 0;
- my $luns = {};
-
- eval {
- $sid = get_sid($scfg, $volname);
- };
- die "$@" if $@;
- if ($sid < 0) {
- # We have no active sessions so make one
- eval {
- $sid = create_session($scfg, $volname);
- };
- die "$@" if $@;
- # Since no session existed prior to this call deactivate all LUN's found
- deactivate_luns($scfg, $volname);
- } else {
- eval {
- $luns = build_lun_list($scfg, $sid);
- };
- die "$@" if $@;
- }
-
- return $luns;
+ my ($class, $storeid, $scfg, $volname) = @_;
+
+ my $sid = 0;
+ my $luns = {};
+
+ eval {
+ $sid = get_sid($scfg, $volname);
+ };
+ die "$@" if $@;
+ if ($sid < 0) {
+ # We have no active sessions so make one
+ eval {
+ $sid = create_session($scfg, $volname);
+ };
+ die "$@" if $@;
+ # Since no session existed prior to this call deactivate all LUN's found
+ deactivate_luns($scfg, $volname);
+ } else {
+ eval {
+ $luns = build_lun_list($scfg, $sid);
+ };
+ die "$@" if $@;
+ }
+
+ return $luns;
}
sub rescan_session {
- my ($class, $storeid, $scfg, $volname, $exclude_lun) = @_;
-
- eval {
- my $active_luns = get_active_luns($class, $storeid, $scfg, $volname);
- delete $active_luns->{$exclude_lun} if defined $exclude_lun;
- my $sid = get_sid($scfg, $volname);
- die "Missing session" if $sid < 0;
- os_request("iscsiadm -m session -r $sid -R", 0, 60);
- deactivate_luns($scfg, $volname, $active_luns);
- delete_session($scfg, $sid) if !%$active_luns;
- };
- die "$@" if $@;
+ my ($class, $storeid, $scfg, $volname, $exclude_lun) = @_;
+
+ eval {
+ my $active_luns = get_active_luns($class, $storeid, $scfg, $volname);
+ delete $active_luns->{$exclude_lun} if defined $exclude_lun;
+ my $sid = get_sid($scfg, $volname);
+ die "Missing session" if $sid < 0;
+ os_request("iscsiadm -m session -r $sid -R", 0, 60);
+ deactivate_luns($scfg, $volname, $active_luns);
+ delete_session($scfg, $sid) if !%$active_luns;
+ };
+ die "$@" if $@;
}
sub freenas_get_latest_snapshot {
@@ -736,13 +735,13 @@ sub freenas_get_latest_snapshot {
my $vname = ($class->parse_volname($volname))[1];
# abort rollback if snapshot is not the latest
- my $response = freenas_request($scfg, 'GET', "storage/snapshot");
- die HTTP::Status::status_message($response) if $response =~ /^\d+$/;
- my $snapshots = decode_json($response);
-
+ my $response = freenas_request($scfg, 'GET', "storage/snapshot");
+ die HTTP::Status::status_message($response) if $response =~ /^\d+$/;
+ my $snapshots = decode_json($response);
+
my $recentsnap;
foreach my $snapshot (@$snapshots) {
- next unless $snapshot->{filesystem} =~ /$scfg->{pool}\/$vname/ && $snapshot->{mostrecent};
+ next unless $snapshot->{filesystem} =~ /$scfg->{pool}\/$vname/ && $snapshot->{mostrecent};
$recentsnap = $snapshot->{name};
last;
}
@@ -758,42 +757,42 @@ sub type {
sub plugindata {
return {
- content => [ {images => 1, rootdir => 1}, {images => 1 , rootdir => 1} ],
- format => [ { raw => 1 } , 'raw' ],
+ content => [ {images => 1, rootdir => 1}, {images => 1 , rootdir => 1} ],
+ format => [ { raw => 1 } , 'raw' ],
};
}
sub properties {
return {
password => {
- description => "password",
- type => "string",
+ description => "password",
+ type => "string",
},
portal_group => {
- description => "Portal Group ID",
- type => "integer",
+ description => "Portal Group ID",
+ type => "integer",
},
initiator_group => {
- description => "Initiator Group ID",
- type => "integer",
+ description => "Initiator Group ID",
+ type => "integer",
},
};
}
sub options {
return {
- portal => { fixed => 1 },
- pool => { fixed => 1 },
- portal_group => { fixed => 1 },
- initiator_group => { fixed => 1 },
- blocksize => { optional => 1 },
- username => { optional => 1 },
- password => { optional => 1 },
-# sparse => { optional => 1 }, not available in 9.2.x. Appear in 11.x
+ portal => { fixed => 1 },
+ pool => { fixed => 1 },
+ portal_group => { fixed => 1 },
+ initiator_group => { fixed => 1 },
+ blocksize => { optional => 1 },
+ username => { optional => 1 },
+ password => { optional => 1 },
+# sparse => { optional => 1 }, not available in 9.2.x. Appear in 11.x
# in 9.2.x all zvols are created sparse!
- nodes => { optional => 1 },
- disable => { optional => 1 },
- content => { optional => 1 },
+ nodes => { optional => 1 },
+ disable => { optional => 1 },
+ content => { optional => 1 },
};
}
@@ -802,14 +801,14 @@ sub options {
sub volume_size_info {
my ($class, $scfg, $storeid, $volname, $timeout) = @_;
- my (undef, $vname) = $class->parse_volname($volname);
+ my (undef, $vname) = $class->parse_volname($volname);
- my $response = freenas_request($scfg, 'GET', "storage/volume/$scfg->{pool}/zvols/$vname");
- die HTTP::Status::status_message($response) if $response =~ /^\d+$/;
- my $zvol = decode_json($response);
-
- return $zvol->{volsize} if $zvol && $zvol->{volsize};
-
+ my $response = freenas_request($scfg, 'GET', "storage/volume/$scfg->{pool}/zvols/$vname");
+ die HTTP::Status::status_message($response) if $response =~ /^\d+$/;
+ my $zvol = decode_json($response);
+
+ return $zvol->{volsize} if $zvol && $zvol->{volsize};
+
die "Could not get zfs volume size\n";
}
@@ -817,9 +816,9 @@ sub parse_volname {
my ($class, $volname) = @_;
if ($volname =~ m/^(((base)-(\d+)-\S+)\/)?((base|vm)-(\d+)-\S+)$/) {
- my $format = 'raw';
- my $isBase = ($6 eq 'base');
- return ('images', $5, $7, $2, $4, $isBase, $format);
+ my $format = 'raw';
+ my $isBase = ($6 eq 'base');
+ return ('images', $5, $7, $2, $4, $isBase, $format);
}
die "unable to parse freenas volume name '$volname'\n";
@@ -833,9 +832,9 @@ sub status {
my $active = 0;
eval {
- my $response = freenas_request($scfg, 'GET', "storage/volume/$scfg->{pool}");
- die HTTP::Status::status_message($response) if $response =~ /^\d+$/;
- my $vol = decode_json($response);
+ my $response = freenas_request($scfg, 'GET', "storage/volume/$scfg->{pool}");
+ die HTTP::Status::status_message($response) if $response =~ /^\d+$/;
+ my $vol = decode_json($response);
my $children = $vol->{children};
if (@$children) {
$used = $children->[0]{used};
@@ -861,27 +860,27 @@ sub list_images {
if (my $dat = $cache->{freenas}->{$zfspool}) {
- foreach my $image (keys %$dat) {
-
- my $info = $dat->{$image};
- my $volname = $info->{name};
- my $parent = $info->{parent};
- my $owner = $info->{vmid};
-
- if ($parent) {
- $info->{volid} = "$storeid:$parent/$volname";
- } else {
- $info->{volid} = "$storeid:$volname";
- }
-
- if ($vollist) {
- my $found = grep { $_ eq $info->{volid} } @$vollist;
- next if !$found;
- } else {
- next if defined ($vmid) && ($owner ne $vmid);
- }
- push @$res, $info;
- }
+ foreach my $image (keys %$dat) {
+
+ my $info = $dat->{$image};
+ my $volname = $info->{name};
+ my $parent = $info->{parent};
+ my $owner = $info->{vmid};
+
+ if ($parent) {
+ $info->{volid} = "$storeid:$parent/$volname";
+ } else {
+ $info->{volid} = "$storeid:$volname";
+ }
+
+ if ($vollist) {
+ my $found = grep { $_ eq $info->{volid} } @$vollist;
+ next if !$found;
+ } else {
+ next if defined ($vmid) && ($owner ne $vmid);
+ }
+ push @$res, $info;
+ }
}
return $res;
@@ -889,16 +888,14 @@ sub list_images {
sub path {
my ($class, $scfg, $volname, $storeid, $snapname) = @_;
- #die "direct access to snapshots not implemented"
- #if defined($snapname);
my ($vtype, $vname, $vmid) = $class->parse_volname($volname);
- $vname = "$vname\@$snapname" if $snapname;
+ $vname = "$vname\@$snapname" if $snapname;
- my $luns = get_active_luns($class, $storeid, $scfg, $vname);
- my $path = disk_by_path($scfg, $vname);
-
+ my $luns = get_active_luns($class, $storeid, $scfg, $vname);
+ my $path = disk_by_path($scfg, $vname);
+
return ($path, $vmid, $vtype);
}
@@ -915,42 +912,42 @@ sub create_base {
my $newname = $name;
$newname =~ s/^vm-/base-/;
- $target = freenas_get_target($scfg, $vmid);
- die "create_base-> missing target" unless $target;
- my $extent = freenas_get_extent($scfg, $name);
- die "create_base-> missing extent" unless $extent;
- my $tg2exent = freenas_get_target_to_exent($scfg, $extent, $target);
- die "create_base-> missing target to extent" unless $tg2exent;
- $lun = freenas_get_lun_number($scfg, $name);
- die "create_base-> missing LUN" unless defined $lun;
- freenas_delete_target_to_exent($scfg, $tg2exent);
- freenas_delete_extent($scfg, $extent);
- my $sid = get_sid($scfg, $name);
- if ($sid >= 0) {
- my $lid = build_lun_list($scfg, $sid, $lun);
- if ($lid && $lid->{$lun}) {
- remove_local_lun($lid->{$lun});
- }
- }
-
- eval {
- # FreeNAS API does not support renaming a zvol so create a snapshot
- # and make a clone of the snapshot instead
- $class->volume_snapshot($scfg, $storeid, $name, $snap);
-
- my $data = {
- name => "$scfg->{pool}/$newname"
- };
- my $response = freenas_request($scfg, 'POST', "storage/snapshot/$scfg->{pool}/$name\@$snap/clone/", encode_json($data));
- die HTTP::Status::status_message($response) if $response =~ /^\d+$/;
-
- freenas_create_lun($scfg, $vmid, $newname);
+ $target = freenas_get_target($scfg, $vmid);
+ die "create_base-> missing target" unless $target;
+ my $extent = freenas_get_extent($scfg, $name);
+ die "create_base-> missing extent" unless $extent;
+ my $tg2exent = freenas_get_target_to_exent($scfg, $extent, $target);
+ die "create_base-> missing target to extent" unless $tg2exent;
+ $lun = freenas_get_lun_number($scfg, $name);
+ die "create_base-> missing LUN" unless defined $lun;
+ freenas_delete_target_to_exent($scfg, $tg2exent);
+ freenas_delete_extent($scfg, $extent);
+ my $sid = get_sid($scfg, $name);
+ if ($sid >= 0) {
+ my $lid = build_lun_list($scfg, $sid, $lun);
+ if ($lid && $lid->{$lun}) {
+ remove_local_lun($lid->{$lun});
+ }
+ }
+
+ eval {
+ # FreeNAS API does not support renaming a zvol so create a snapshot
+ # and make a clone of the snapshot instead
+ $class->volume_snapshot($scfg, $storeid, $name, $snap);
+
+ my $data = {
+ name => "$scfg->{pool}/$newname"
+ };
+ my $response = freenas_request($scfg, 'POST', "storage/snapshot/$scfg->{pool}/$name\@$snap/clone/", encode_json($data));
+ die HTTP::Status::status_message($response) if $response =~ /^\d+$/;
+
+ freenas_create_lun($scfg, $vmid, $newname);
};
if ($@) {
- $extent = freenas_create_extent($scfg, $name);
- die "create_base-> Could not create extent for VM '$vmid'" unless $extent;
- $tg2exent = freenas_create_target_to_exent($scfg, $target, $extent, $lun);
- die "create_base-> Could not create target to extend for VM '$vmid'" unless defined $tg2exent;
+ $extent = freenas_create_extent($scfg, $name);
+ die "create_base-> Could not create extent for VM '$vmid'" unless $extent;
+ $tg2exent = freenas_create_target_to_exent($scfg, $target, $extent, $lun);
+ die "create_base-> Could not create target to extend for VM '$vmid'" unless defined $tg2exent;
}
return $newname;
@@ -966,30 +963,30 @@ sub clone_image {
die "clone_image only works on base images" if !$isBase;
- my $run = PVE::QemuServer::check_running($basevmid);
- if (!$run) {
- $run = PVE::LXC::check_running($basevmid);
- }
-
+ my $run = PVE::QemuServer::check_running($basevmid);
+ if (!$run) {
+ $run = PVE::LXC::check_running($basevmid);
+ }
+
my $name = freenas_find_free_diskname($storeid, $scfg, $vmid, $format);
- $class->volume_snapshot($scfg, $storeid, $basename, $snap);
-
- my $data = {
- name => "$scfg->{pool}/$name"
- };
- my $response = freenas_request($scfg, 'POST', "storage/snapshot/$scfg->{pool}/$basename\@$snap/clone/", encode_json($data));
- die HTTP::Status::status_message($response) if $response =~ /^\d+$/;
+ $class->volume_snapshot($scfg, $storeid, $basename, $snap);
+
+ my $data = {
+ name => "$scfg->{pool}/$name"
+ };
+ my $response = freenas_request($scfg, 'POST', "storage/snapshot/$scfg->{pool}/$basename\@$snap/clone/", encode_json($data));
+ die HTTP::Status::status_message($response) if $response =~ /^\d+$/;
- $name = "$basename/$name";
+ $name = "$basename/$name";
# get ZFS dataset name from PVE volname
my (undef, $clonedname) = $class->parse_volname($name);
- freenas_create_lun($scfg, $vmid, $clonedname);
-
- my $res = $class->deactivate_volume($storeid, $scfg, $basename) unless $run;
- warn "Could not deactivate volume '$basename'" unless $res;
-
+ freenas_create_lun($scfg, $vmid, $clonedname);
+
+ my $res = $class->deactivate_volume($storeid, $scfg, $basename) unless $run;
+ warn "Could not deactivate volume '$basename'" unless $res;
+
return $name;
}
@@ -1009,15 +1006,15 @@ sub alloc_image {
my $zvol = freenas_create_zvol($scfg, $volname, $size);
eval {
- freenas_create_lun($scfg, $vmid, $zvol) if $zvol;
+ freenas_create_lun($scfg, $vmid, $zvol) if $zvol;
};
if ($@) {
- my $err = $@;
- eval {
- freenas_delete_zvol($scfg, $volname);
- };
- $err .= "\n$@" if $@;
- die $err;
+ my $err = $@;
+ eval {
+ freenas_delete_zvol($scfg, $volname);
+ };
+ $err .= "\n$@" if $@;
+ die $err;
}
return $volname;
@@ -1028,39 +1025,39 @@ sub free_image {
my ($vtype, $name, $vmid, $basename) = $class->parse_volname($volname);
- eval {
- my $target = freenas_get_target($scfg, $vmid);
- die "free_image-> missing target" unless $target;
- my $extent = freenas_get_extent($scfg, $name);
- die "free_image-> missing extent" unless $extent;
- my $tg2exent = freenas_get_target_to_exent($scfg, $extent, $target);
- die "free_image-> missing target to extent" unless $tg2exent;
- my $target_group = freenas_get_target_group($scfg, $target);
- die "free_image-> missing target group" unless $target_group;
- my $lun = freenas_get_lun_number($scfg, $name);
- die "free_image-> missing LUN" unless defined $lun;
-
- my $res = $class->deactivate_volume($storeid, $scfg, $volname);
- warn "Could not deactivate volume '$volname'" unless $res;
- freenas_delete_target_to_exent($scfg, $tg2exent);
- freenas_delete_extent($scfg, $extent);
- if ($target && freenas_no_more_extents($scfg, $target)) {
- if ($target_group) {
- freenas_delete_target_group($scfg, $target_group);
- }
- freenas_delete_target($scfg, $target);
- }
- freenas_delete_zvol($scfg, $name);
- $class->volume_snapshot_delete($scfg, $storeid, $basename, "__base__$vmid") if $basename;
- if ($isBase) {
- $basename = $name;
- $basename =~ s/^base-/vm-/;
- $class->volume_snapshot_delete($scfg, $storeid, $basename, '__base__') if $basename;
- freenas_delete_zvol($scfg, $basename);
- }
- };
+ eval {
+ my $target = freenas_get_target($scfg, $vmid);
+ die "free_image-> missing target" unless $target;
+ my $extent = freenas_get_extent($scfg, $name);
+ die "free_image-> missing extent" unless $extent;
+ my $tg2exent = freenas_get_target_to_exent($scfg, $extent, $target);
+ die "free_image-> missing target to extent" unless $tg2exent;
+ my $target_group = freenas_get_target_group($scfg, $target);
+ die "free_image-> missing target group" unless $target_group;
+ my $lun = freenas_get_lun_number($scfg, $name);
+ die "free_image-> missing LUN" unless defined $lun;
+
+ my $res = $class->deactivate_volume($storeid, $scfg, $volname);
+ warn "Could not deactivate volume '$volname'" unless $res;
+ freenas_delete_target_to_exent($scfg, $tg2exent);
+ freenas_delete_extent($scfg, $extent);
+ if ($target && freenas_no_more_extents($scfg, $target)) {
+ if ($target_group) {
+ freenas_delete_target_group($scfg, $target_group);
+ }
+ freenas_delete_target($scfg, $target);
+ }
+ freenas_delete_zvol($scfg, $name);
+ $class->volume_snapshot_delete($scfg, $storeid, $basename, "__base__$vmid") if $basename;
+ if ($isBase) {
+ $basename = $name;
+ $basename =~ s/^base-/vm-/;
+ $class->volume_snapshot_delete($scfg, $storeid, $basename, '__base__') if $basename;
+ freenas_delete_zvol($scfg, $basename);
+ }
+ };
if ($@) {
- my $err = $@;
+ my $err = $@;
freenas_create_lun($scfg, $vmid, $name) unless $isBase;
die $err;
}
@@ -1079,36 +1076,36 @@ sub volume_resize {
}
die 'mode failure - unable to resize disk(s) on a running system due to FreeNAS bug.<br />
- See bug report: <a href="https://bugs.freenas.org/issues/24432" target="_blank">#24432</a><br />' if $run;
+ See bug report: <a href="https://bugs.freenas.org/issues/24432" target="_blank">#24432</a><br />' if $run;
my $data = {
- volsize => $size,
+ volsize => $size,
};
- my $response = freenas_request($scfg, 'PUT', "storage/volume/$scfg->{pool}/zvols/$name", encode_json($data));
- die HTTP::Status::status_message($response) if $response =~ /^\d+$/;
- my $vol = decode_json($response);
+ my $response = freenas_request($scfg, 'PUT', "storage/volume/$scfg->{pool}/zvols/$name", encode_json($data));
+ die HTTP::Status::status_message($response) if $response =~ /^\d+$/;
+ my $vol = decode_json($response);
- my $sid = get_sid($scfg, $name);
- if ($sid >= 0) {
- eval {
+ my $sid = get_sid($scfg, $name);
+ if ($sid >= 0) {
+ eval {
#### Required because of a bug in FreeNAS: https://bugs.freenas.org/issues/24432
- my $targetname = freenas_get_target_name($scfg, $name);
- die "volume_resize-> Missing target name" unless $targetname;
- my $target = freenas_get_target($scfg, $vmid);
- die "volume_resize-> Missing target" unless $target;
- my $extent = freenas_get_extent($scfg, $name);
- die "volume_resize-> Missing extent" unless $extent;
- my $tg2exent = freenas_get_target_to_exent($scfg, $extent, $target);
- die "volume_resize-> Missing target to extent" unless $tg2exent;
- my $lunid = freenas_get_lun_number($scfg, $name);
- die "volume_resize-> Missing LUN" unless defined $lunid;
- freenas_delete_target_to_exent($scfg, $tg2exent);
- freenas_create_target_to_exent($scfg, $target, $extent, $lunid);
+ my $targetname = freenas_get_target_name($scfg, $name);
+ die "volume_resize-> Missing target name" unless $targetname;
+ my $target = freenas_get_target($scfg, $vmid);
+ die "volume_resize-> Missing target" unless $target;
+ my $extent = freenas_get_extent($scfg, $name);
+ die "volume_resize-> Missing extent" unless $extent;
+ my $tg2exent = freenas_get_target_to_exent($scfg, $extent, $target);
+ die "volume_resize-> Missing target to extent" unless $tg2exent;
+ my $lunid = freenas_get_lun_number($scfg, $name);
+ die "volume_resize-> Missing LUN" unless defined $lunid;
+ freenas_delete_target_to_exent($scfg, $tg2exent);
+ freenas_create_target_to_exent($scfg, $target, $extent, $lunid);
#### Required because of a bug in FreeNAS: https://bugs.freenas.org/issues/24432
- rescan_session($class, $storeid, $scfg, $name, $lunid);
- };
- die "$name: Resize with $size failed. ($@)\n" if $@;
- }
+ rescan_session($class, $storeid, $scfg, $name, $lunid);
+ };
+ die "$name: Resize with $size failed. ($@)\n" if $@;
+ }
return int($vol->{volsize}/1024);
}
@@ -1116,24 +1113,14 @@ sub volume_resize {
sub volume_snapshot {
my ($class, $scfg, $storeid, $volname, $snap) = @_;
- my (undef, $vname, $vmid) = $class->parse_volname($volname);
-
+ my $vname = ($class->parse_volname($volname))[1];
+
my $data = {
- dataset => "$scfg->{pool}/$vname",
- name => $snap,
+ dataset => "$scfg->{pool}/$vname",
+ name => $snap,
};
- 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";
- }
- }
+ my $response = freenas_request($scfg, 'POST', "storage/snapshot/", encode_json($data));
+ die HTTP::Status::status_message($response) if $response =~ /^\d+$/;
}
sub volume_snapshot_delete {
@@ -1141,54 +1128,51 @@ sub volume_snapshot_delete {
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 $@;
- }
+ if ($snap eq 'vzdump') {
+ 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);
+ $class->deactivate_volume($storeid, $scfg, "$vname\@$snap");
+ };
+ 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");
- }
+ die HTTP::Status::status_message($response) if $response =~ /^\d+$/;
}
sub volume_snapshot_rollback {
my ($class, $scfg, $storeid, $volname, $snap) = @_;
- my ($vtype, $name, $vmid) = $class->parse_volname($volname);
- my $target = freenas_get_target($scfg, $vmid);
- die "volume_resize-> Missing target" unless $target;
- my $extent = freenas_get_extent($scfg, $name);
- die "volume_resize-> Missing extent" unless $extent;
- my $tg2exent = freenas_get_target_to_exent($scfg, $extent, $target);
- die "volume_resize-> Missing target to extent" unless $tg2exent;
- my $lunid = freenas_get_lun_number($scfg, $name);
- die "volume_resize-> Missing LUN" unless defined $lunid;
- freenas_delete_target_to_exent($scfg, $tg2exent);
- freenas_delete_extent($scfg, $extent);
-
- my $data = {
- force => bless( do{\(my $o = 0)}, 'JSON::XS::Boolean' ),
- };
+ my ($vtype, $name, $vmid) = $class->parse_volname($volname);
+ my $target = freenas_get_target($scfg, $vmid);
+ die "volume_resize-> Missing target" unless $target;
+ my $extent = freenas_get_extent($scfg, $name);
+ die "volume_resize-> Missing extent" unless $extent;
+ my $tg2exent = freenas_get_target_to_exent($scfg, $extent, $target);
+ die "volume_resize-> Missing target to extent" unless $tg2exent;
+ my $lunid = freenas_get_lun_number($scfg, $name);
+ die "volume_resize-> Missing LUN" unless defined $lunid;
+ freenas_delete_target_to_exent($scfg, $tg2exent);
+ freenas_delete_extent($scfg, $extent);
+
+ my $data = {
+ force => bless( do{\(my $o = 0)}, 'JSON::XS::Boolean' ),
+ };
my $response = freenas_request($scfg, 'POST', "storage/snapshot/$scfg->{pool}/$name\@$snap/rollback/", encode_json($data));
- die HTTP::Status::status_message($response) if $response =~ /^\d+$/;
-
- $extent = freenas_create_extent($scfg, $name);
- freenas_create_target_to_exent($scfg, $target, $extent, $lunid);
- rescan_session($class, $storeid, $scfg, $name, $lunid);
+ die HTTP::Status::status_message($response) if $response =~ /^\d+$/;
+
+ $extent = freenas_create_extent($scfg, $name);
+ freenas_create_target_to_exent($scfg, $target, $extent, $lunid);
+ rescan_session($class, $storeid, $scfg, $name, $lunid);
}
sub volume_rollback_is_possible {
@@ -1198,7 +1182,7 @@ sub volume_rollback_is_possible {
my $recentsnap = $class->freenas_get_latest_snapshot($scfg, $name);
if ($snap ne $recentsnap) {
- die "can't rollback, more recent snapshots exist";
+ die "can't rollback, more recent snapshots exist";
}
return 1;
@@ -1214,21 +1198,21 @@ sub volume_has_feature {
my ($class, $scfg, $feature, $storeid, $volname, $snapname, $running) = @_;
my $features = {
- snapshot => { current => 1, snap => 1},
- clone => { base => 1},
- template => { current => 1},
- copy => { base => 1, current => 1},
+ snapshot => { current => 1, snap => 1},
+ clone => { base => 1},
+ template => { current => 1},
+ copy => { base => 1, current => 1},
};
my ($vtype, $name, $vmid, $basename, $basevmid, $isBase) =
- $class->parse_volname($volname);
+ $class->parse_volname($volname);
my $key = undef;
if ($snapname) {
- $key = 'snap';
+ $key = 'snap';
} else {
- $key = $isBase ? 'base' : 'current';
+ $key = $isBase ? 'base' : 'current';
}
return 1 if $features->{$feature}->{$key};
@@ -1251,8 +1235,8 @@ sub deactivate_storage {
# Procedure for activating a LUN:
#
# if session does not exist
-# login to target
-# deactivate all luns in session
+# login to target
+# deactivate all luns in session
# get list of active luns
# get lun number to activate
# make list of our luns (active + new lun)
@@ -1260,25 +1244,36 @@ sub deactivate_storage {
# deactivate all luns except our luns
sub activate_volume {
my ($class, $storeid, $scfg, $volname, $snapname, $cache) = @_;
+ my $lun;
+
+ my (undef, $name, $vmid) = $class->parse_volname($volname);
+
+ my $active_luns = get_active_luns($class, $storeid, $scfg, $name);
- return if $snapname; # Activated when creating snapshot
-
- my $name = ($class->parse_volname($volname))[1];
+ if ($snapname) {
+ eval {
+ freenas_create_lun($scfg, $vmid, "$name\@$snapname");
+ $lun = freenas_get_lun_number($scfg, "$name\@$snapname");
+ $active_luns->{$lun} = "0:0:0:$lun";
+ };
+ if ($@) {
+ die "$@ - unable to activate snapshot from remote FreeNAS storage";
+ }
+ }
+
+ $lun = freenas_get_lun_number($scfg, $name);
+ $active_luns->{$lun} = "0:0:0:$lun";
- 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";
-
- eval {
- my $sid = get_sid($scfg, $name);
- die "activate_volume-> Missing session" if $sid < 0;
- # Add new LUN's to session
- os_request("iscsiadm -m session -r $sid -R", 0, 60);
- sleep 1;
- # Remove all LUN's from session which is not currently active
- deactivate_luns($scfg, $name, $active_luns);
- };
- die "$@" if $@;
+ eval {
+ my $sid = get_sid($scfg, $name);
+ die "activate_volume-> Missing session" if $sid < 0;
+ # Add new LUN's to session
+ os_request("iscsiadm -m session -r $sid -R", 0, 60);
+ sleep 1;
+ # Remove all LUN's from session which is not currently active
+ deactivate_luns($scfg, $name, $active_luns);
+ };
+ die "$@" if $@;
return 1;
}
@@ -1286,26 +1281,25 @@ sub activate_volume {
# Procedure for deactivating a LUN:
#
# if session exists
-# get lun number to deactivate
-# deactivate lun
+# get lun number to deactivate
+# deactivate lun
sub deactivate_volume {
my ($class, $storeid, $scfg, $volname, $snapname, $cache) = @_;
- 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);
- delete $active_luns->{$lun};
-
- eval {
- my $sid = get_sid($scfg, $name);
- die "deactivate_volume-> Missing session" if $sid < 0;
- deactivate_luns($scfg, $name, $active_luns);
- delete_session($scfg, $sid) if !%$active_luns;
- };
- die $@ if $@;
+ my $active_luns = get_active_luns($class, $storeid, $scfg, $name);
+
+ my $lun = freenas_get_lun_number($scfg, $name);
+ delete $active_luns->{$lun};
+
+ eval {
+ my $sid = get_sid($scfg, $name);
+ die "deactivate_volume-> Missing session" if $sid < 0;
+ deactivate_luns($scfg, $name, $active_luns);
+ delete_session($scfg, $sid) if !%$active_luns;
+ };
+ die $@ if $@;
return 1;
}
--
2.11.0
----
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