--- ZFSPlugin.pm.orig 2018-11-27 07:23:15.000000000 -0500 +++ ZFSPlugin.pm 2018-12-15 09:24:08.393984276 -0500 @@ -10,6 +10,7 @@ use base qw(PVE::Storage::ZFSPoolPlugin); use PVE::Storage::LunCmd::Comstar; +use PVE::Storage::LunCmd::FreeNAS; use PVE::Storage::LunCmd::Istgt; use PVE::Storage::LunCmd::Iet; use PVE::Storage::LunCmd::LIO; @@ -26,13 +27,14 @@ modify_lu => 1, add_view => 1, list_view => 1, + list_extent => 1, list_lu => 1, }; my $zfs_unknown_scsi_provider = sub { my ($provider) = @_; - die "$provider: unknown iscsi provider. Available [comstar, istgt, iet, LIO]"; + die "$provider: unknown iscsi provider. Available [comstar, freenas, istgt, iet, LIO]"; }; my $zfs_get_base = sub { @@ -40,6 +42,8 @@ if ($scfg->{iscsiprovider} eq 'comstar') { return PVE::Storage::LunCmd::Comstar::get_base; + } elsif ($scfg->{iscsiprovider} eq 'freenas') { + return PVE::Storage::LunCmd::FreeNAS::get_base; } elsif ($scfg->{iscsiprovider} eq 'istgt') { return PVE::Storage::LunCmd::Istgt::get_base; } elsif ($scfg->{iscsiprovider} eq 'iet') { @@ -62,6 +66,8 @@ if ($lun_cmds->{$method}) { if ($scfg->{iscsiprovider} eq 'comstar') { $msg = PVE::Storage::LunCmd::Comstar::run_lun_command($scfg, $timeout, $method, @params); + } elsif ($scfg->{iscsiprovider} eq 'freenas') { + $msg = PVE::Storage::LunCmd::FreeNAS::run_lun_command($scfg, $timeout, $method, @params); } elsif ($scfg->{iscsiprovider} eq 'istgt') { $msg = PVE::Storage::LunCmd::Istgt::run_lun_command($scfg, $timeout, $method, @params); } elsif ($scfg->{iscsiprovider} eq 'iet') { @@ -160,6 +166,15 @@ return $class->zfs_request($scfg, undef, 'list_view', $guid); } +# Part of the multipath enhancement +sub zfs_get_wwid_number { + my ($class, $scfg, $guid) = @_; + + die "could not find lun_number for guid $guid" if !$guid; + + return $class->zfs_request($scfg, undef, 'list_extent', $guid); +} + # Configuration sub type { @@ -178,6 +193,24 @@ description => "iscsi provider", type => 'string', }, + # This is for FreeNAS iscsi and API intergration + # And some enhancements asked by the community + freenas_user => { + description => "FreeNAS API Username", + type => 'string', + }, + freenas_password => { + description => "FreeNAS API Password", + type => 'string', + }, + freenas_use_ssl => { + description => "FreeNAS API access via SSL", + type => 'boolean', + }, + freenas_apiv4_host => { + description => "FreeNAS API Host", + type => 'string', + }, # this will disable write caching on comstar and istgt. # it is not implemented for iet. iet blockio always operates with # writethrough caching when not in readonly mode @@ -205,14 +238,18 @@ nodes => { optional => 1 }, disable => { optional => 1 }, portal => { fixed => 1 }, - target => { fixed => 1 }, - pool => { fixed => 1 }, + target => { fixed => 0 }, + pool => { fixed => 0 }, blocksize => { fixed => 1 }, iscsiprovider => { fixed => 1 }, nowritecache => { optional => 1 }, sparse => { optional => 1 }, comstar_hg => { optional => 1 }, comstar_tg => { optional => 1 }, + freenas_user => { optional => 1 }, + freenas_password => { optional => 1 }, + freenas_use_ssl => { optional => 1 }, + freenas_apiv4_host => { optional => 1 }, lio_tpg => { optional => 1 }, content => { optional => 1 }, bwlimit => { optional => 1 }, @@ -237,6 +274,40 @@ my $path = "iscsi://$portal/$target/$lun"; + # Multipath enhancement + eval { + my $wwid = $class->zfs_get_wwid_number($scfg, $guid); +# syslog(info,"JD: path get_lun_number guid $guid"); + + if ($wwid =~ /^([-\@\w.]+)$/) { + $wwid = $1; # $data now untainted + } else { + die "Bad data in '$wwid'"; # log this somewhere + } + my $wwid_end = substr $wwid, 16; + + my $mapper = ''; + sleep 3; + run_command("iscsiadm -m session --rescan"); + sleep 3; + my $line = `multipath -ll | grep \"$wwid_end\"`; + my ($mapper_device) = split(' ', $line); + $mapper_device = "" unless $mapper_device; + $mapper .= $mapper_device; + + if ($mapper =~ /^([-\@\w.]+)$/) { + $mapper = $1; # $data now untainted + } else { + $mapper = ''; + } + +# syslog(info,"Multipath mapper found: $mapper\n"); + if ($mapper ne "") { + $path = "/dev/mapper/$mapper"; + sleep 5; + } + }; + return ($path, $vmid, $vtype); }