xcat-core/xCAT-server/lib/xcat/plugins/iscsi.pm
jbjohnso ea2114d9ef Fix problem where tgtadm as of late frequently prefers iSER, which would be great but has some steeper underlying requirements that make it harder to use.
Software iscsi for now continues to be intended primarily for prototyping, with an expectation of beefier storage.

git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@13926 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd
2012-10-01 19:52:23 +00:00

186 lines
6.4 KiB
Perl

package xCAT_plugin::iscsi;
use strict;
use xCAT::Table;
use xCAT::TableUtils;
use Socket;
use File::Path;
use File::Basename;
use Getopt::Long;
Getopt::Long::Configure("bundling");
Getopt::Long::Configure("pass_through");
sub handled_commands {
return {
"setupiscsidev" => "iscsi",
};
}
sub get_tid {
#generate a unique tid given a node for tgtadm to use
my $node = shift;
my $tid = unpack("N",inet_aton($node));
$tid = $tid & ((2**31)-1);
return $tid;
}
sub preprocess_request {
my $request = shift;
my $callback = shift;
my @requests = ();
my %iscsiserverhash;
if ($request->{_xcatpreprocessed}->[0] == 1) { return [$request]; }
my $iscsitab = xCAT::Table->new('iscsi');
foreach my $node (@{$request->{node}}) {
my $tent = $iscsitab->getNodeAttribs($node,['server']);
if ($tent and $tent->{server}) {
$iscsiserverhash{$tent->{server}}->{$node} = 1;
} else {
$callback->({error=>["No iscsi.server for $node, aborting request"]});
return [];
}
}
foreach my $iscsis (keys %iscsiserverhash) {
my $reqcopy = {%$request};
$reqcopy->{'_xcatdest'} = $iscsis;
$reqcopy->{_xcatpreprocessed}->[0] = 1;
$reqcopy->{node} = [ keys %{$iscsiserverhash{$iscsis}} ];
push @requests,$reqcopy;
}
return \@requests;
}
sub process_request {
my $request = shift;
my $callback = shift;
unless (-x "/usr/sbin/tgtadm") {
$callback->({error=>"/usr/sbin/tgtadm does not exist, iSCSI plugin currently requires it, please install scsi-target-utils package under CentOS, RHEL, or Fedora. SLES support is not yet implemented",errorcode=>[1]});
return;
}
my $lunsize = 4096;
if ($request->{arg}) {
@ARGV=@{$request->{arg}};
GetOptions(
"size|s=i" => \$lunsize,
);
}
my $iscsitab = xCAT::Table->new('iscsi');
my @nodes = @{$request->{node}};
#my $sitetab = xCAT::Table->new('site');
#unless ($sitetab) {
# $callback->({error=>"Fatal error opening site table",errorcode=>[1]});
# return;
#}
my $domain;
#(my $ipent) = $sitetab->getAttribs({key=>'domain'},'value');
my @entries = xCAT::TableUtils->get_site_attribute("domain");
my $t_entry = $entries[0];
if ( defined($t_entry) ) { $domain = $t_entry; }
#($ipent) = $sitetab->getAttribs({key=>'iscsidir'},'value');
my $iscsiprefix;
my @entries = xCAT::TableUtils->get_site_attribute("iscsidir");
my $t_entry = $entries[0];
if ( defined($t_entry) ) {
$iscsiprefix = $t_entry;
}
foreach my $node (@nodes) {
my $fileloc;
my %rsp;
%rsp=(name=>[$node]);
my $iscsient = $iscsitab->getNodeAttribs($node,['file']);
if ($iscsient and $iscsient->{file}) {
$fileloc = $iscsient->{file};
unless ($fileloc =~ /^\//) {
unless ($iscsiprefix) {
$rsp{error}=["$node: Unable to identify file to back iSCSI LUN, no iscsidir in site table and iscsi.file entry for node is a relative path"];
$rsp{errorcode}=[1];
$callback->({node=>[\%rsp]});
%rsp=(name=>[$node]);
next;
}
$fileloc=$iscsiprefix."/".$iscsient->{file};
}
} else {
unless ($iscsiprefix) {
$rsp{error}=["$node: Unable to identify file to back iSCSI LUN, no iscsidir in site table nor iscsi.file entry for node (define at least either)"];
$rsp{errorcode}=[1];
$callback->({node=>[\%rsp]});
%rsp=(name=>[$node]);
next;
}
$fileloc = "$iscsiprefix/$node";
$iscsitab->setNodeAttribs($node,{file=>$fileloc});
}
unless (-d dirname($fileloc)) {
mkpath dirname($fileloc);
}
unless (-f $fileloc) {
$rsp{name}=[$node];
$rsp{data}=["Creating $fileloc ($lunsize MB)"];
$callback->({node=>[\%rsp]});
%rsp=(name=>[$node]);
$lunsize -= 1;
my $rc = system("dd if=/dev/zero of=$fileloc bs=1M count=1 seek=$lunsize");
$lunsize += 1;
if ($rc) {
$rsp{error}=["dd process exited with return code $rc"];
$rsp{errorcode} = [1];
$callback->({node=>[\%rsp]});
%rsp=(name=>[$node]);
next;
}
}
my $targname;
my $lun;
$iscsient = $iscsitab->getNodeAttribs($node,['target','lun']);
if ($iscsient and $iscsient->{target}) {
$targname = $iscsient->{target};
}
if ($iscsient and defined($iscsient->{lun})) {
$lun = $iscsient->{lun};
} else {
$lun = '1';
$iscsitab->setNodeAttribs($node,{lun=>$lun});
}
unless ($targname) {
my @date = localtime;
my $year = 1900+$date[5];
my $month = $date[4];
$targname = "iqn.$year-$month.$domain:$node";
$iscsitab->setNodeAttribs($node,{target=>$targname});
}
system("tgtadm --lld iscsi --mode target --op delete --tid ".get_tid($node)." -T $targname");
my $rc = system("tgtadm --lld iscsi --mode target --op new --tid ".get_tid($node)." -T $targname");
if ($rc) {
$rsp{error}=["tgtadm --lld iscsi --mode target --op new --tid ".get_tid($node)." -T $targname returned $rc"];
if ($rc == 27392) {
push @{$rsp{error}},"This likely indicates the need to do /etc/init.d/tgtd start";
}
$rsp{errorcode} = [1];
$callback->({node=>[\%rsp]});
%rsp=(name=>[$node]);
next;
}
$rc = system("tgtadm --lld iscsi --mode logicalunit --op new --tid ".get_tid($node)." --lun 1 --backing-store $fileloc --device-type disk");
if ($rc) {
$rsp{error}=["tgtadm --lld iscsi mode logicalunit --op new --tid ".get_tid($node)." --lun 1 --backing-store $fileloc returned $rc"];
$rsp{errorcode} = [1];
$callback->({node=>[\%rsp]});
%rsp=(name=>[$node]);
next;
}
$rc = system("tgtadm --lld iscsi --mode target --op bind --tid ".get_tid($node)." -I ".inet_ntoa(inet_aton($node)));
if ($rc) {
$rsp{error}=["tgtadm --lld iscsi --mode target --op bind --tid ".get_tid($node)." -I ".inet_ntoa(inet_aton($node)) . " returned $rc"];
$rsp{errorcode} = [1];
$callback->({node=>[\%rsp]});
%rsp=(name=>[$node]);
} else {
$rsp{data}=["iSCSI LUN configured"];
$callback->({node=>[\%rsp]});
%rsp=(name=>[$node]);
}
}
}
1;