mirror of
				https://github.com/xcat2/xcat-core.git
				synced 2025-10-30 19:02:27 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			182 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
			
		
		
	
	
			182 lines
		
	
	
		
			6.7 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 $nd          = xCAT::NetworkUtils->getNodeDomains(\@nodes);
 | |
|     my %nodedomains = %{$nd};
 | |
| 
 | |
|     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];
 | |
|             my $domain = $nodedomains{$node};
 | |
|             $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;
 |