xcat-core/xCAT-server/lib/xcat/plugins/ontap.pm
2009-07-22 21:07:47 +00:00

134 lines
3.9 KiB
Perl

# IBM(c) 2009 EPL license http://www.eclipse.org/legal/epl-v10.html
#This plugin handles 'setupiscsidev' operation for ONTAP platform devices,
#such as the IBM N-series storage subsystems.
#It requires that the storage enclosure have root's public key as an
#authorized key for passwordless
package xCAT_plugin::ontap;
#In ONTAP world, the entire controller is a particular target iqn, that shows
#different lun numbers depending on client iqn.
#iscsi.target, iscsi.server, and iscsi.lun may therefore look identital
#for multiple nodes, but mean entirely different things
#This plugin will populate the lun and targetname
use strict;
BEGIN
{
$::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat';
}
use lib "$::XCATROOT/lib/perl";
use warnings "all";
use xCAT::Table;
sub handled_commands {
return {
testontap => 'ontap',
# setupiscsidev => iscsi:method
#Mayhaps need an iscsiserver table? iscsi table column has a pretty weak
#association, but on the other hand, iscsi servers aren't necessarily a node
#So two options:
# Add field to iscsi table to declare the mechanism to setup device:
# Pros:
# -No extra 'nodes' required to be defined
# Cons:
# -Could be awkward if the enviornment has hybrid iscsi storage providers
# Add new table
# Pros: allows the management method of the target to be abstracted from the node
# cons: requires that every iscsi entity be defined as a node
}
}
my %iscsicfg;
sub process_request {
my $request = shift;
my $callback = shift;
my $iscsitab = xCAT::Table->new('iscsi');
my @nodes = @{$request->{node}};
my $iscsitabdata = $iscsitab->getNodesAttribs(\@nodes,[qw/server iname file/]);
my $node;
foreach $node (keys %$iscsitabdata) { #Re-layout the data so we can iterate target-wise rather than node wise
$iscsicfg{$iscsitabdata->{$node}->[0]->{server}}->{$node}=$iscsitabdata->{$node}->[0];
}
my $controller;
foreach $controller (keys %iscsicfg) { #TODO: we need to forkify this
#Develop serially first, then put fork semantics in place
handle_targets($controller,$request);
}
use Data::Dumper;
print Dumper(\%iscsicfg);
};
sub get_controller_iqn {
my $controller = shift;
my $output = `ssh $controller iscsi nodename`;
$output =~ s/^[^:]*://;
chomp $output;
$output =~ s/^\s*//;
return $output;
}
sub get_luns_for_iqn {
#extract all the backing files presented to the given iqn, with lun id
my $controller = shift;
my $iqn = shift;
my @output = `ssh $controller igroup show `;
my %returns;
my $groupname;
my $tgr;
foreach (@output) {
if (/^ ([^ ]+)/) { #This is a new group
$tgr = $1;
} elsif (/^ $iqn/) {
$groupname = $tgr;
}
}
unless ($groupname) {
return undef;
}
@output = `ssh $controller lun show -m`;
shift @output; #discard header
shift @output;
foreach (@output) {
unless (/iSCSI/) { next; }
my $backing;
my $igr;
my $lunid;
($backing,$igr,$lunid) = split /\s+/,$_,3;
if ($igr eq $groupname) {
$returns{$backing}=$lunid;
}
}
return \%returns;
}
sub handle_targets {
my $controller = shift;
my $request = shift;
my $node;
print get_controller_iqn($controller);
foreach $node (keys %{$iscsicfg{$controller}}) {
configure_node($controller,$node,$request);
}
}
sub configure_node {
my $controller = shift;
my $node = shift;
my $request = shift;
my $lunsize;
if ($request->{arg}) {
@ARGV=@{$request->{arg}};
GetOptions(
"size|s=i" => \$lunsize,
);
}
my $current_view = get_luns_for_iqn($controller,$iscsicfg{$controller}->{$node}->{iname});
print Dumper($current_view);
}
1;