diff --git a/README.md b/README.md index 1f07550..a64361c 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Please be aware that this enhancment uses the FreeNAS APIs and NOT the ssh/scp like the other interface provides. -1. First use the following commands to patch the needed files forthe FreeNAS Interface +1. First use the following commands to patch the needed files for the FreeNAS Interface ```bash patch -b /usr/share/pve-manager/js/pvemanagerlib.js < pve-manager/js/pvemanagerlib.js.patch patch -b /usr/share/perl5/PVE/Storage/ZFSPlugin.pm < perl5/PVE/Storage/ZFSPlugin.pm.patch diff --git a/perl5/PVE/Storage/ZFSPlugin.pm.patch b/perl5/PVE/Storage/ZFSPlugin.pm.patch index c42814c..1896f53 100644 --- a/perl5/PVE/Storage/ZFSPlugin.pm.patch +++ b/perl5/PVE/Storage/ZFSPlugin.pm.patch @@ -1,5 +1,5 @@ ---- ZFSPlugin.pm.orig 2018-05-16 04:06:14.000000000 -0400 -+++ ZFSPlugin.pm 2018-08-19 15:44:12.472851999 -0400 +--- ZFSPlugin.pm.5.2-8.pm.orig 2018-08-29 12:24:44.171123901 -0400 ++++ ZFSPlugin.pm 2018-10-15 12:17:52.026049903 -0400 @@ -10,6 +10,7 @@ use base qw(PVE::Storage::ZFSPoolPlugin); @@ -7,24 +7,17 @@ +use PVE::Storage::LunCmd::FreeNAS; use PVE::Storage::LunCmd::Istgt; use PVE::Storage::LunCmd::Iet; - -@@ -25,13 +26,14 @@ - modify_lu => 1, - add_view => 1, - list_view => 1, -+ list_extent => 1, - list_lu => 1, - }; - + use PVE::Storage::LunCmd::LIO; +@@ -32,7 +33,7 @@ my $zfs_unknown_scsi_provider = sub { my ($provider) = @_; -- die "$provider: unknown iscsi provider. Available [comstar, istgt, iet]"; -+ die "$provider: unknown iscsi provider. Available [comstar, freenas, istgt, iet]"; +- 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 { -@@ -39,6 +41,8 @@ +@@ -40,6 +41,8 @@ if ($scfg->{iscsiprovider} eq 'comstar') { return PVE::Storage::LunCmd::Comstar::get_base; @@ -33,7 +26,7 @@ } elsif ($scfg->{iscsiprovider} eq 'istgt') { return PVE::Storage::LunCmd::Istgt::get_base; } elsif ($scfg->{iscsiprovider} eq 'iet') { -@@ -59,6 +63,8 @@ +@@ -62,6 +65,8 @@ if ($lun_cmds->{$method}) { if ($scfg->{iscsiprovider} eq 'comstar') { $msg = PVE::Storage::LunCmd::Comstar::run_lun_command($scfg, $timeout, $method, @params); @@ -42,10 +35,11 @@ } elsif ($scfg->{iscsiprovider} eq 'istgt') { $msg = PVE::Storage::LunCmd::Istgt::run_lun_command($scfg, $timeout, $method, @params); } elsif ($scfg->{iscsiprovider} eq 'iet') { -@@ -155,6 +161,14 @@ +@@ -160,6 +165,15 @@ return $class->zfs_request($scfg, undef, 'list_view', $guid); } ++# Part of the multipath enhancement +sub zfs_get_wwid_number { + my ($class, $scfg, $guid) = @_; + @@ -57,80 +51,79 @@ # Configuration sub type { -@@ -173,6 +187,22 @@ +@@ -178,6 +192,23 @@ description => "iscsi provider", type => 'string', }, -+ 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 is for FreeNAS iscsi and API intergration ++ 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 -@@ -204,6 +234,10 @@ +@@ -213,6 +244,10 @@ 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 }, ++ 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 }, - }; -@@ -225,7 +259,41 @@ - my $guid = $class->zfs_get_lu_name($scfg, $name); - my $lun = $class->zfs_get_lun_number($scfg, $guid); +@@ -237,6 +272,40 @@ -- my $path = "iscsi://$portal/$target/$lun"; -+ my $wwid = $class->zfs_get_wwid_number($scfg, $guid); -+# syslog(info,"JD: path get_lun_number guid $uid"); -+ -+ 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; -+ -+ my $path = ""; -+ -+ if ($mapper =~ /^([-\@\w.]+)$/) { -+ $mapper = $1; # $data now untainted -+ } else { -+ $mapper = ''; -+ } -+ -+# syslog(info,"Mapper: $mapper\n"); -+ if ($mapper eq "") -+ { -+ $path = "iscsi://$portal/$target/$lun"; -+ } else { -+ $path = "/dev/mapper/$mapper"; -+ sleep 5; -+ } + 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); } + diff --git a/pve-manager/js/pvemanagerlib.js.patch b/pve-manager/js/pvemanagerlib.js.patch index 5bd8066..77f3ae4 100644 --- a/pve-manager/js/pvemanagerlib.js.patch +++ b/pve-manager/js/pvemanagerlib.js.patch @@ -1,85 +1,99 @@ ---- pvemanagerlib.js.orig 2018-07-30 23:13:28.045035059 -0400 -+++ pvemanagerlib.js.new 2018-08-19 10:42:58.494724196 -0400 -@@ -5379,6 +5379,7 @@ - alias: ['widget.pveiScsiProviderSelector'], - comboItems: [ - ['comstar', 'Comstar'], -+ ['freenas', 'FreeNAS-API'], - [ 'istgt', 'istgt'], - [ 'iet', 'IET'] - ] -@@ -27361,7 +27362,23 @@ +--- pvemanagerlib-5.2-9.js 2018-10-16 07:17:21.915593478 -0400 ++++ pvemanagerlib.js 2018-10-16 07:24:32.280291338 -0400 +@@ -28574,6 +28574,7 @@ + data: { + isLIO: false, + isComstar: true, ++ isFreeNAS: false, + hasWriteCacheOption: true + } + }, +@@ -28586,10 +28587,18 @@ + } + }, + changeISCSIProvider: function(f, newVal, oldVal) { ++ var me = this; + var vm = this.getViewModel(); + vm.set('isLIO', newVal === 'LIO'); + vm.set('isComstar', newVal === 'comstar'); +- vm.set('hasWriteCacheOption', newVal === 'comstar' || newVal === 'istgt'); ++ vm.set('isFreeNAS', newVal === 'freenas'); ++ vm.set('hasWriteCacheOption', newVal === 'comstar' || newVal === 'freenas' || newVal === 'istgt'); ++ if (newVal !== 'freenas') { ++ me.lookupReference('freenas_use_ssl_field').setValue(false); ++ me.lookupReference('freenas_apiv4_host_field').setValue(''); ++ me.lookupReference('freenas_user_field').setValue(''); ++ me.lookupReference('freenas_password_field').setValue(''); ++ } + } + }, + +@@ -28648,8 +28657,28 @@ + name: 'comstar_tg', value: '', fieldLabel: gettext('Target group'), +- bind: me.isCreate ? { disabled: '{!isComstar}' } : { hidden: '{!isComstar}' }, ++ bind: me.isCreate ? { hidden: '{!isComstar}' } : { hidden: '{!isComstar}' }, allowBlank: true -- } + }, + { + xtype: 'proxmoxcheckbox', + name: 'freenas_use_ssl', ++ reference: 'freenas_use_ssl_field', ++ inputId: 'freenas_use_ssl_field', + checked: false, ++ bind: me.isCreate ? { hidden: '{!isFreeNAS}' } : { hidden: '{!isFreeNAS}' }, + uncheckedValue: 0, -+ hidden: me.iscsiprovider !== "freenas", -+ fieldLabel: gettext('FreeNAS API use SSL') ++ fieldLabel: gettext('API use SSL') + }, + { + xtype: me.isCreate ? 'textfield' : 'displayfield', + name: 'freenas_user', ++ reference: 'freenas_user_field', ++ inputId: 'freenas_user_field', + value: '', -+ hidden: me.iscsiprovider !== "freenas", -+ fieldLabel: gettext('FreeNAS User'), -+ allowBlank: true -+ }, ++ fieldLabel: gettext('API Username'), ++ bind: me.isCreate ? { hidden: '{!isFreeNAS}' } : { hidden: '{!isFreeNAS}' }, ++ allowBlank: me.isFreeNAS ? false : true + } ]; - me.column2 = [ -@@ -27370,7 +27387,26 @@ - name: 'iscsiprovider', - value: 'comstar', - fieldLabel: gettext('iSCSI Provider'), -- allowBlank: false -+ allowBlank: false, -+ listeners: { -+ change: function(f, value) { -+ if (value === "freenas") { -+ me.down('field[name=freenas_use_ssl]').setHidden(false); -+ me.down('field[name=freenas_apiv4_host]').setHidden(false); -+ me.down('field[name=freenas_user]').setHidden(false); -+ me.down('field[name=freenas_password]').setHidden(false); -+ } else { -+ me.down('field[name=freenas_use_ssl]').setHidden(true); -+ me.down('field[name=freenas_use_ssl]').setValue(false); -+ me.down('field[name=freenas_apiv4_host]').setHidden(true); -+ me.down('field[name=freenas_apiv4_host]').setValue(false); -+ me.down('field[name=freenas_user]').setHidden(true); -+ me.down('field[name=freenas_user]').setValue(''); -+ me.down('field[name=freenas_password]').setHidden(true); -+ me.down('field[name=freenas_password]').setValue(''); -+ } -+ } -+ } - }, - { - xtype: 'proxmoxcheckbox', -@@ -27392,6 +27428,22 @@ +@@ -28680,7 +28709,7 @@ + xtype: me.isCreate ? 'textfield' : 'displayfield', + name: 'comstar_hg', value: '', +- bind: me.isCreate ? { disabled: '{!isComstar}' } : { hidden: '{!isComstar}' }, ++ bind: me.isCreate ? { hidden: '{!isComstar}' } : { hidden: '{!isComstar}' }, fieldLabel: gettext('Host group'), allowBlank: true + }, +@@ -28688,9 +28717,27 @@ + xtype: me.isCreate ? 'textfield' : 'displayfield', + name: 'lio_tpg', + value: '', +- bind: me.isCreate ? { disabled: '{!isLIO}' } : { hidden: '{!isLIO}' }, +- allowBlank: false, +- fieldLabel: gettext('Target portal group') ++ bind: me.isCreate ? { hidden: '{!isLIO}' } : { hidden: '{!isLIO}' }, ++ fieldLabel: gettext('Target portal group'), ++ allowBlank: true + }, + { + xtype: me.isCreate ? 'textfield' : 'displayfield', + name: 'freenas_apiv4_host', ++ reference: 'freenas_apiv4_host_field', + value: '', -+ hidden: me.iscsiprovider !== "freenas", ++ bind: me.isCreate ? { hidden: '{!isFreeNAS}' } : { hidden: '{!isFreeNAS}' }, + fieldLabel: gettext('API IPv4 Host'), + allowBlank: true + }, + { + xtype: me.isCreate ? 'textfield' : 'displayfield', + name: 'freenas_password', ++ reference: 'freenas_password_field', + value: '', -+ hidden: me.iscsiprovider !== "freenas", -+ fieldLabel: gettext('FreeNAS Password'), ++ bind: me.isCreate ? { hidden: '{!isFreeNAS}' } : { hidden: '{!isFreeNAS}' }, ++ fieldLabel: gettext('API Password'), + allowBlank: true } ];