2008-02-04 16:55:14 +00:00
package xCAT_plugin::iscsi ;
2008-07-18 19:39:51 +00:00
use strict ;
2008-02-04 16:55:14 +00:00
use xCAT::Table ;
use Socket ;
2008-03-04 16:07:44 +00:00
use File::Path ;
2008-03-11 12:54:32 +00:00
use File::Basename ;
2008-02-04 16:55:14 +00:00
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 ;
2008-07-18 19:39:51 +00:00
if ( $ request - > { _xcatdest } ) { return [ $ request ] ; }
2008-02-04 16:55:14 +00:00
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 - > { 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 ;
}
2008-05-28 14:38:55 +00:00
my $ lunsize = 4096 ;
2008-07-28 18:27:24 +00:00
if ( $ request - > { arg } ) {
2008-07-23 23:56:19 +00:00
@ ARGV = @ { $ request - > { arg } } ;
GetOptions (
"size|s=i" = > \ $ lunsize ,
) ;
}
2008-02-04 16:55:14 +00:00
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' ) ;
if ( $ ipent and $ ipent - > { value } ) { $ domain = $ ipent - > { value } ; }
( $ ipent ) = $ sitetab - > getAttribs ( { key = > 'iscsidir' } , 'value' ) ;
my $ iscsiprefix ;
if ( $ ipent and $ ipent - > { value } ) {
$ iscsiprefix = $ ipent - > { value } ;
}
foreach my $ node ( @ nodes ) {
my $ fileloc ;
2008-03-04 19:38:16 +00:00
my % rsp ;
% rsp = ( name = > [ $ node ] ) ;
2008-02-04 16:55:14 +00:00
my $ iscsient = $ iscsitab - > getNodeAttribs ( $ node , [ 'file' ] ) ;
if ( $ iscsient and $ iscsient - > { file } ) {
$ fileloc = $ iscsient - > { file } ;
2008-03-11 12:54:32 +00:00
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 ;
}
2008-03-11 13:01:35 +00:00
$ fileloc = $ iscsiprefix . "/" . $ iscsient - > { file } ;
2008-03-11 12:54:32 +00:00
}
2008-02-04 16:55:14 +00:00
} else {
unless ( $ iscsiprefix ) {
2008-03-11 12:54:32 +00:00
$ 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)" ] ;
2008-03-04 19:38:16 +00:00
$ rsp { errorcode } = [ 1 ] ;
$ callback - > ( { node = > [ \ % rsp ] } ) ;
% rsp = ( name = > [ $ node ] ) ;
2008-02-04 16:55:14 +00:00
next ;
}
$ fileloc = "$iscsiprefix/$node" ;
$ iscsitab - > setNodeAttribs ( $ node , { file = > $ fileloc } ) ;
}
2008-03-11 12:54:32 +00:00
unless ( - d dirname ( $ fileloc ) ) {
mkpath dirname ( $ fileloc ) ;
}
2008-02-04 16:55:14 +00:00
unless ( - f $ fileloc ) {
2008-03-04 19:38:16 +00:00
$ rsp { name } = [ $ node ] ;
$ rsp { data } = [ "Creating $fileloc ($lunsize MB)" ] ;
$ callback - > ( { node = > [ \ % rsp ] } ) ;
% rsp = ( name = > [ $ node ] ) ;
2008-03-26 13:17:16 +00:00
$ lunsize -= 1 ;
2008-03-11 13:01:35 +00:00
my $ rc = system ( "dd if=/dev/zero of=$fileloc bs=1M count=1 seek=$lunsize" ) ;
2008-02-04 16:55:14 +00:00
if ( $ rc ) {
2008-03-04 19:38:16 +00:00
$ rsp { error } = [ "dd process exited with return code $rc" ] ;
$ rsp { errorcode } = [ 1 ] ;
$ callback - > ( { node = > [ \ % rsp ] } ) ;
% rsp = ( name = > [ $ node ] ) ;
2008-02-04 16:55:14 +00:00
next ;
}
}
my $ targname ;
$ iscsient = $ iscsitab - > getNodeAttribs ( $ node , [ 'target' ] ) ;
if ( $ iscsient and $ iscsient - > { target } ) {
$ targname = $ iscsient - > { target } ;
}
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 --mode target --op delete --tid " . get_tid ( $ node ) . " -T $targname" ) ;
my $ rc = system ( "tgtadm --mode target --op new --tid " . get_tid ( $ node ) . " -T $targname" ) ;
if ( $ rc ) {
2008-03-04 19:38:16 +00:00
$ rsp { error } = [ "tgtadm --mode target --op new --tid " . get_tid ( $ node ) . " -T $targname returned $rc" ] ;
2008-03-11 13:01:35 +00:00
if ( $ rc == 27392 ) {
push @ { $ rsp { error } } , "This likely indicates the need to do /etc/init.d/tgtd start" ;
}
2008-03-04 19:38:16 +00:00
$ rsp { errorcode } = [ 1 ] ;
$ callback - > ( { node = > [ \ % rsp ] } ) ;
% rsp = ( name = > [ $ node ] ) ;
2008-02-04 16:55:14 +00:00
next ;
}
$ rc = system ( "tgtadm --mode logicalunit --op new --tid " . get_tid ( $ node ) . " --lun 1 --backing-store $fileloc --device-type disk" ) ;
if ( $ rc ) {
2008-03-04 19:38:16 +00:00
$ rsp { error } = [ "tgtadm --mode logicalunit --op new --tid " . get_tid ( $ node ) . " --lun 1 --backing-store $fileloc returned $rc" ] ;
$ rsp { errorcode } = [ 1 ] ;
$ callback - > ( { node = > [ \ % rsp ] } ) ;
% rsp = ( name = > [ $ node ] ) ;
2008-02-04 16:55:14 +00:00
next ;
}
$ rc = system ( "tgtadm --mode target --op bind --tid " . get_tid ( $ node ) . " -I " . inet_ntoa ( inet_aton ( $ node ) ) ) ;
if ( $ rc ) {
2008-03-04 19:38:16 +00:00
$ rsp { error } = [ "tgtadm --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 ] ) ;
2008-02-04 16:55:14 +00:00
}
}
}
1 ;