Merge pull request #48 from NojuHD/fc-support

Add support for SCSI (Fibre Channel)
This commit is contained in:
Timur Kumakbayev
2025-02-10 09:00:52 +05:00
committed by GitHub
2 changed files with 89 additions and 11 deletions
+88 -11
View File
@@ -8,6 +8,7 @@ use Data::Dumper qw( Dumper ); # DEBUG
use IO::File ();
use Net::IP ();
use File::Path ();
use File::Spec ();
use PVE::JSONSchema ();
use PVE::Network ();
@@ -31,8 +32,9 @@ $Data::Dumper::Terse = 1; # Removes `$VAR1 =` in output
$Data::Dumper::Indent = 1; # Outputs everything in one line
$Data::Dumper::Useqq = 1; # Uses quotes for strings
my $purestorage_wwn_prefix = "624a9370";
my $default_hgsuffix = "";
my $purestorage_wwn_prefix = '624a9370';
my $default_hgsuffix = '';
my $default_protocol = 'iscsi';
my $DEBUG = 0;
@@ -76,29 +78,34 @@ sub properties {
return {
hgsuffix => {
description => "Host group suffx.",
type => "string",
type => 'string',
default => $default_hgsuffix
},
address => {
description => "PureStorage Management IP address or DNS name.",
type => "string"
type => 'string'
},
token => {
description => "Storage API token.",
type => "string"
type => 'string'
},
podname => {
description => 'PureStorage pod name',
description => "PureStorage pod name",
type => 'string'
},
vnprefix => {
description => 'Prefix to add to volume name before sending it to PureStorage array',
description => "Prefix to add to volume name before sending it to PureStorage array",
type => 'string'
},
check_ssl => {
description => "Verify the server's TLS certificate",
type => "boolean",
default => "no"
type => 'boolean',
default => 'no'
},
protocol => {
description => "Set storage protocol ( iscsi | fc | nvme )",
type => 'string',
default => $default_protocol
},
};
}
@@ -113,6 +120,7 @@ sub options {
podname => { optional => 1 },
vnprefix => { optional => 1 },
check_ssl => { optional => 1 },
protocol => { optional => 1 },
nodes => { optional => 1 },
disable => { optional => 1 },
content => { optional => 1 },
@@ -139,6 +147,57 @@ sub exec_command {
}
}
sub scsi_scan_new {
print "Debug :: PVE::Storage::Custom::PureStoragePlugin::sub::scsi_scan_new\n" if $DEBUG;
my $fc_base = '/sys/class/fc_host';
my @fc_hosts = glob( "$fc_base/*" );
die "Error :: sub::scsi_scan_new did not find fibre channel hosts.\n" unless @fc_hosts;
foreach my $fc_host ( @fc_hosts ) {
next unless ( $fc_host =~ m/^(\/sys\/class\/fc_host\/\w+)$/ );
my $adapter = basename( $1 );
my $scsi_host = File::Spec->catfile( "/sys/class/scsi_host/", $adapter );
if ( -d $scsi_host ) {
open my $fh, '>', File::Spec->catfile( $scsi_host, "scan" ) or die "Error :: Cannot open file: $!";
print $fh "- - -\n";
close $fh;
} else {
warn "Warning :: SCSI host path $scsi_host does not exist.\n";
}
}
}
sub scsi_rescan_device {
my ( $wwid ) = @_;
print "Debug :: PVE::Storage::Custom::PureStoragePlugin::sub::scsi_rescan_device\n" if $DEBUG;
die "Error :: sub::scsi_rescan_device did not recive a wwid.\n" unless $wwid;
foreach my $device ( glob( '/sys/class/scsi_device/*' ) ) {
next unless ( $device =~ m/^(\/sys\/class\/scsi_device\/[\d\:\\]+)$/ );
my $tmppath = $1;
my $wwid_file = File::Spec->catfile( $tmppath, "device/wwid" );
next unless -f $wwid_file;
open( my $wwid_fh, '<', $wwid_file ) or die "Error :: Cannot open file: $!";
my $tmpwwid = <$wwid_fh>;
close( $wwid_fh );
$tmpwwid =~ s/^naa\.//;
$tmpwwid = "3" . lc( $tmpwwid );
chomp( $tmpwwid );
if ( $tmpwwid eq $wwid ) {
open my $rescan, '>', File::Spec->catfile( $tmppath, "device/rescan" ) or die "Error :: Cannot open file: $!";
print $rescan "1\n";
close $rescan;
}
}
exec_command( [ $cmd->{ multipath }, '-r', $wwid ], 1 );
}
sub multipath_check {
my ( $wwid ) = @_;
my $output = `$cmd->{ "multipath" } -l $wwid`;
@@ -651,7 +710,16 @@ sub purestorage_resize_volume {
my ( $path, $wwid ) = $class->purestorage_get_wwn( $scfg, $volname );
exec_command( [ $cmd->{ iscsiadm }, '--mode', 'node', '--rescan' ], 1 );
my $protocol = $scfg->{ protocol } // $default_protocol;
if ( $protocol eq 'iscsi' ) {
exec_command( [ $cmd->{ iscsiadm }, '--mode', 'node', '--rescan' ], 1 );
} elsif ( $protocol eq 'fc' ) {
scsi_rescan_device( $wwid );
} elsif ( $protocol eq 'nvme' ) {
die qq{Error :: Protocol: "$protocol" isn't implemented yet.\n};
} else {
die qq{Error :: Protocol: "$protocol" isn't a valid protocol.\n};
}
exec_command( [ $cmd->{ multipathd }, 'resize', 'map', $wwid ], 1 );
@@ -963,7 +1031,16 @@ sub map_volume {
print "Debug :: Mapping volume \"$volname\" with WWN: " . uc( $wwid ) . ".\n" if $DEBUG;
exec_command( [ $cmd->{ iscsiadm }, '--mode', 'session', '--rescan' ], 1 );
my $protocol = $scfg->{ protocol } // $default_protocol;
if ( $protocol eq 'iscsi' ) {
exec_command( [ $cmd->{ iscsiadm }, '--mode', 'session', '--rescan' ], 1 );
} elsif ( $protocol eq 'fc' ) {
scsi_scan_new();
} elsif ( $protocol eq 'nvme' ) {
die qq{Error :: Protocol: "$protocol" isn't implemented yet.\n};
} else {
die qq{Error :: Protocol: "$protocol" isn't a valid protocol.\n};
}
my $path_exists = sub {
return -e $path;
+1
View File
@@ -131,6 +131,7 @@ purestorage: <storage_id>
| vnprefix | (`optional`) The prefix to prepend to name of virtual disks. |
| hgsuffix | (`optional`) A suffix that is appended to the hostname when the plugin interacts with the Pure Storage array. This can help differentiate hosts if necessary. |
| content | Specifies the types of content that can be stored. For virtual machine disk images, use images. |
| protocol | (`optional`, default is `iscsi`) Specifies the storage protocol (iscsi, fc) |
> **_NOTE:_** Ensure that the token and other sensitive information are kept secure and not exposed publicly.