mirror of
				https://github.com/xcat2/xcat-core.git
				synced 2025-11-04 13:22:36 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			512 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
			
		
		
	
	
			512 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
# IBM(c) 2013 EPL license http://www.eclipse.org/legal/epl-v10.html
 | 
						|
#----------------------------------------------------------------------
 | 
						|
 | 
						|
# Plugin to interface with IBM SVC managed storage
 | 
						|
#
 | 
						|
use strict;
 | 
						|
 | 
						|
package xCAT_plugin::svc;
 | 
						|
 | 
						|
use xCAT::SvrUtils qw/sendmsg/;
 | 
						|
use xCAT::SSHInteract;
 | 
						|
use Getopt::Long;
 | 
						|
Getopt::Long::Configure("bundling");
 | 
						|
Getopt::Long::Configure("pass_through");
 | 
						|
 | 
						|
my $callback;
 | 
						|
my $dorequest;
 | 
						|
my %controllersessions;
 | 
						|
 | 
						|
sub handled_commands {
 | 
						|
    return {
 | 
						|
        mkstorage => "storage:type",
 | 
						|
        lsstorage => "storage:type",
 | 
						|
        detachstorage => "storage:type",
 | 
						|
        rmstorage => "storage:type",
 | 
						|
        lspool => "storage:type",
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
sub detachstorage {
 | 
						|
    my $request = shift;
 | 
						|
    my @nodes = @{$request->{node}};
 | 
						|
    my $controller;
 | 
						|
    @ARGV = @{$request->{arg}};
 | 
						|
    unless (GetOptions(
 | 
						|
        'controller=s' => \$controller,
 | 
						|
        )) {
 | 
						|
        foreach (@nodes) {
 | 
						|
            sendmsg([1,"Error parsing arguments"],$callback,$_);
 | 
						|
        }
 | 
						|
    }
 | 
						|
    my $storagetab = xCAT::Table->new('storage');
 | 
						|
    my $storents = $storagetab->getNodesAttribs(\@nodes, [qw/controller/]);
 | 
						|
    unless ($controller) {
 | 
						|
        $controller = assure_identical_table_values(\@nodes, $storents, 'controller');
 | 
						|
    }
 | 
						|
    my @volnames = @ARGV;
 | 
						|
    my $wwns = get_wwns(@nodes);
 | 
						|
    use Data::Dumper;
 | 
						|
    my %namemap = makehosts($wwns, controller=>$controller, cfg=>$storents);
 | 
						|
    foreach my $node (keys %namemap) {
 | 
						|
        my $host = $namemap{$node};
 | 
						|
        my $session = establish_session(controller=>$controller);
 | 
						|
        foreach my $volname (@volnames) {
 | 
						|
            my @rets = $session->cmd("rmvdiskhostmap -host $host $volname");
 | 
						|
            my $ret = $rets[0];
 | 
						|
            if ($ret =~ m/^CMMVC5842E/) {
 | 
						|
                sendmsg([1,"Node not attached to $volname"],$callback,$node);
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
sub rmstorage {
 | 
						|
    my $request = shift;
 | 
						|
    my @nodes = @{$request->{node}};
 | 
						|
    my $controller;
 | 
						|
    @ARGV = @{$request->{arg}};
 | 
						|
    unless (GetOptions(
 | 
						|
        'controller=s' => \$controller,
 | 
						|
        )) {
 | 
						|
        foreach (@nodes) {
 | 
						|
            sendmsg([1,"Error parsing arguments"],$callback,$_);
 | 
						|
        }
 | 
						|
    }
 | 
						|
    my @volnames = @ARGV;
 | 
						|
    my $storagetab = xCAT::Table->new('storage');
 | 
						|
    my $storents = $storagetab->getNodesAttribs(\@nodes, [qw/controller/]);
 | 
						|
    unless ($controller) {
 | 
						|
        $controller = assure_identical_table_values(\@nodes, $storents, 'controller');
 | 
						|
    }
 | 
						|
    detachstorage($request);
 | 
						|
    my $session = establish_session(controller=>$controller);
 | 
						|
    foreach my $volname (@volnames) {
 | 
						|
        my @info = $session->cmd("rmvdisk $volname");
 | 
						|
        my $ret = $info[0];
 | 
						|
        if ($ret =~ m/^CMMVC5753E/) {
 | 
						|
            foreach my $node (@nodes) {
 | 
						|
                sendmsg([1,"Disk $volname does not exist"], $callback, @nodes);
 | 
						|
            }
 | 
						|
        } elsif ($ret =~ m/^CMMVC5840E/) {
 | 
						|
            foreach my $node (@nodes) {
 | 
						|
                sendmsg([1,"Disk $volname is mapped to other nodes and/or busy"], $callback, @nodes);
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
sub lsstorage {
 | 
						|
    my $request = shift;
 | 
						|
    my @nodes = @{$request->{node}};
 | 
						|
    my $storagetab = xCAT::Table->new("storage",-create=>0);
 | 
						|
    unless ($storagetab) { return; }
 | 
						|
    my $storents = $storagetab->getNodesAttribs(\@nodes,[qw/controller/]);
 | 
						|
    my $wwns = get_wwns(@nodes);
 | 
						|
    foreach my $node (@nodes) {
 | 
						|
        if ($storents and $storents->{$node} and $storents->{$node}->[0]->{controller}) {
 | 
						|
            my $ctls = $storents->{$node}->[0]->{controller};
 | 
						|
            foreach my $ctl (split /,/, $ctls) { # TODO: scan all controllers at once
 | 
						|
                my $session = establish_session(controller=>$ctl);
 | 
						|
                my %namemap = makehosts($wwns, controller=>$ctl, cfg=>$storents);
 | 
						|
                my @vdisks = hashifyoutput($session->cmd("lsvdisk -delim :"));
 | 
						|
                foreach my $vdisk (@vdisks) {
 | 
						|
                    my @maps = hashifyoutput($session->cmd("lsvdiskhostmap -delim : ".$vdisk->{'id'}));
 | 
						|
                    foreach my $map (@maps) {
 | 
						|
                        if ($map->{host_name} eq $namemap{$node}) {
 | 
						|
                            sendmsg($vdisk->{name}.': size: '.$vdisk->{capacity}.' id: '.$vdisk->{vdisk_UID},$callback,$node);
 | 
						|
                            last; 
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
sub mkstorage {
 | 
						|
    my $request = shift;
 | 
						|
    my @nodes = @{$request->{node}};
 | 
						|
    my $shared = 0;
 | 
						|
    my $controller;
 | 
						|
    my $pool;
 | 
						|
    my $size;
 | 
						|
    my $boot = 0;
 | 
						|
    my $format = 0;
 | 
						|
    unless (ref $request->{arg}) {
 | 
						|
        die "TODO: usage";
 | 
						|
    }
 | 
						|
    my $name;
 | 
						|
    @ARGV = @{$request->{arg}};
 | 
						|
    unless (GetOptions(
 | 
						|
        'format' => \$format,
 | 
						|
        'shared' => \$shared,
 | 
						|
        'controller=s' => \$controller,
 | 
						|
        'boot' => \$boot,
 | 
						|
        'size=f' => \$size,
 | 
						|
        'name=s' => \$name,
 | 
						|
        'pool=s' => \$pool,
 | 
						|
        )) {
 | 
						|
        foreach (@nodes) {
 | 
						|
            sendmsg([1,"Error parsing arguments"],$callback,$_);
 | 
						|
        }
 | 
						|
    }
 | 
						|
    if ($shared and $boot) {
 | 
						|
        foreach (@nodes) {
 | 
						|
            sendmsg([1,"Storage can not be both shared and boot"],$callback,$_);
 | 
						|
        }
 | 
						|
    }
 | 
						|
    my $storagetab = xCAT::Table->new('storage');
 | 
						|
    my $storents = $storagetab->getNodesAttribs(\@nodes,
 | 
						|
        [qw/controller storagepool size/]);
 | 
						|
    if ($shared) {
 | 
						|
        unless ($size) {
 | 
						|
            foreach (@nodes) {
 | 
						|
                sendmsg([1,
 | 
						|
                     "Size for shared volumes must be specified as an argument"
 | 
						|
                    ], $callback,$_);
 | 
						|
            }
 | 
						|
        }
 | 
						|
        unless ($pool) {
 | 
						|
            $pool = assure_identical_table_values(\@nodes, $storents, 'storagepool');
 | 
						|
        }
 | 
						|
        unless ($controller) {
 | 
						|
            $controller = assure_identical_table_values(\@nodes, $storents, 'controller');
 | 
						|
        }
 | 
						|
        unless (defined $pool and defined $controller) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        my %lunargs = (controller=>$controller, size=>$size, pool=>$pool);
 | 
						|
        if ($name) { $lunargs{name} = $name; }
 | 
						|
        my $lun = create_lun(%lunargs);
 | 
						|
        sendmsg($lun->{name}.": id: ".$lun->{wwn},$callback);
 | 
						|
        my $wwns = get_wwns(@nodes);
 | 
						|
        my %namemap = makehosts($wwns, controller=>$controller, cfg=>$storents);
 | 
						|
        my @names = values %namemap;
 | 
						|
        bindhosts(\@names, $lun, controller=>$controller);
 | 
						|
        if ($format) {
 | 
						|
            my %request = (
 | 
						|
                node => [$nodes[0]],
 | 
						|
                command => [ 'formatdisk' ],
 | 
						|
                arg => [ '--id', $lun->{wwn}, '--name', $lun->{name} ]
 | 
						|
            );
 | 
						|
            $dorequest->(\%request, $callback);
 | 
						|
            %request = (
 | 
						|
                node => \@nodes,
 | 
						|
                command => [ 'rescansan' ],
 | 
						|
            );
 | 
						|
            $dorequest->(\%request, $callback);
 | 
						|
        }
 | 
						|
    } else {
 | 
						|
        foreach my $node (@nodes) {
 | 
						|
            mkstorage_single(node=>$node, size=>$size, pool=>$pool,
 | 
						|
                             boot=>$boot, name=>$name, controller=>$controller,
 | 
						|
                             cfg=>$storents->{$node});
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
sub hashifyoutput {
 | 
						|
    my @svcoutput = @_;
 | 
						|
    my $hdr = shift @svcoutput;
 | 
						|
    my @columns = split /:/, $hdr;
 | 
						|
    my @ret;
 | 
						|
    foreach my $line (@svcoutput) {
 | 
						|
        my $index = 0;
 | 
						|
        my %record = ();
 | 
						|
        my $keyname;
 | 
						|
        foreach my $datum (split /:/, $line) {
 | 
						|
            $keyname = $columns[$index];
 | 
						|
            $record{$keyname} = $datum;
 | 
						|
            $index += 1;
 | 
						|
        }
 | 
						|
        push @ret,\%record;
 | 
						|
    }
 | 
						|
    pop @ret; # discard data from prompt
 | 
						|
    return @ret;
 | 
						|
}
 | 
						|
sub bindhosts {
 | 
						|
    my $nodes = shift;
 | 
						|
    my $lun = shift;
 | 
						|
    my %args = @_;
 | 
						|
    my $session = establish_session(%args);
 | 
						|
    foreach my $node (@$nodes) {
 | 
						|
        #TODO: get what failure looks like... somehow...
 | 
						|
        #I guess I could make something with mismatched name and see how it
 | 
						|
        #goes
 | 
						|
        $session->cmd("mkvdiskhostmap -force -host $node ".$lun->{id});
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
sub fixup_host {
 | 
						|
    my $session = shift;
 | 
						|
    my $wwnlist = shift;
 | 
						|
    my @hosts = hashifyoutput($session->cmd("lshost -delim :"));
 | 
						|
    my %wwnmap;
 | 
						|
    my %hostmap;
 | 
						|
    foreach my $host (@hosts) {
 | 
						|
        my @hostd = $session->cmd("lshost -delim : ".$host->{name});
 | 
						|
        foreach my $hdatum (@hostd) {
 | 
						|
            if ($hdatum =~ m/^WWPN:(.*)$/) {
 | 
						|
                $wwnmap{$1} = $host->{name};
 | 
						|
                $hostmap{$host->{name}}->{$1} = 1;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
    my $name;
 | 
						|
    foreach my $wwn (@$wwnlist) {
 | 
						|
        $wwn =~ s/://g;
 | 
						|
        $wwn = uc($wwn);
 | 
						|
        if (defined $wwnmap{$wwn}) { # found the matching host
 | 
						|
            #we want to give the host all the ports that may be relevant
 | 
						|
            $name = $wwnmap{$wwn};
 | 
						|
            foreach my $mwwn (@$wwnlist) {
 | 
						|
                $mwwn =~ s/://g;
 | 
						|
                $mwwn = uc($mwwn);
 | 
						|
                if (not defined $hostmap{$name}->{$mwwn}) {
 | 
						|
                    $session->cmd("addhostport -hbawwpn $mwwn -force $name");
 | 
						|
                }
 | 
						|
            }
 | 
						|
            return $name;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    die "unable to find host to fixup";
 | 
						|
}
 | 
						|
 | 
						|
sub makehosts {
 | 
						|
    my $wwnmap = shift;
 | 
						|
    my %args = @_;
 | 
						|
    my $session = establish_session(%args);
 | 
						|
    my $stortab = xCAT::Table->new('storage');
 | 
						|
    my %nodenamemap;
 | 
						|
    foreach my $node (keys %$wwnmap) {
 | 
						|
        my $wwnstr = "";
 | 
						|
        foreach my $wwn (@{$wwnmap->{$node}}) {
 | 
						|
            $wwn =~ s/://g;
 | 
						|
            $wwnstr .= $wwn . ":";
 | 
						|
        }
 | 
						|
        chop($wwnstr);
 | 
						|
        #TODO: what if the given wwn exists, but *not* as the nodename we want
 | 
						|
        #the correct action is to look at hosts, see if one exists, and reuse,
 | 
						|
        #create, or warn depending
 | 
						|
        my @hostres = $session->cmd("mkhost -name $node -hbawwpn $wwnstr -force");
 | 
						|
        my $result = $hostres[0];
 | 
						|
        if ($result =~ m/^CMM/) { # we have some exceptional case....
 | 
						|
            if ($result =~ m/^CMMVC6035E/) { #duplicate name and/or wwn..
 | 
						|
                #need to finde the host and massage it to being viable
 | 
						|
                $nodenamemap{$node} = fixup_host($session, $wwnmap->{$node});
 | 
						|
            } else {
 | 
						|
                die $result." while trying to create host";
 | 
						|
            }
 | 
						|
        } else {
 | 
						|
            $nodenamemap{$node} = $node;
 | 
						|
        }
 | 
						|
        my @currentcontrollers = split /,/, $args{cfg}->{$node}->[0]->{controller};
 | 
						|
        if ($args{cfg}->{$node}->[0] and $args{cfg}->{$node}->[0]->{controller}) {
 | 
						|
            @currentcontrollers = split /,/, $args{cfg}->{$node}->[0]->{controller};
 | 
						|
        } else {
 | 
						|
            @currentcontrollers = ();
 | 
						|
        }
 | 
						|
        if (grep { $_ eq $args{controller}} @currentcontrollers) {
 | 
						|
            next;
 | 
						|
        }
 | 
						|
        unshift @currentcontrollers, $args{controller};
 | 
						|
        my $ctrstring = join ",", @currentcontrollers;
 | 
						|
        $stortab->setNodeAttribs($node,{controller=>$ctrstring});
 | 
						|
    }
 | 
						|
    return %nodenamemap;
 | 
						|
}
 | 
						|
 | 
						|
my %wwnmap;
 | 
						|
sub got_wwns {
 | 
						|
    my $rsp = shift;
 | 
						|
    foreach my $ndata (@{$rsp->{node}}) {
 | 
						|
        my $nodename = $ndata->{name}->[0];
 | 
						|
        my @wwns = ();
 | 
						|
        foreach my $data (@{$ndata->{data}}) {
 | 
						|
            push @{$wwnmap{$nodename}}, $data->{contents}->[0];
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
sub get_wwns {
 | 
						|
    %wwnmap = ();
 | 
						|
    my @nodes = @_;
 | 
						|
    foreach my $node (@nodes) {
 | 
						|
        $wwnmap{$node} = [];
 | 
						|
    }
 | 
						|
    my %request = (
 | 
						|
        node => \@nodes,
 | 
						|
        command => [ 'rinv' ],
 | 
						|
        arg => [ 'wwn' ]
 | 
						|
    );
 | 
						|
    $dorequest->(\%request, \&got_wwns);
 | 
						|
    return \%wwnmap;
 | 
						|
}
 | 
						|
 | 
						|
my $globaluser;
 | 
						|
my $globalpass;
 | 
						|
sub get_svc_creds {
 | 
						|
    my $controller = shift;
 | 
						|
    if ($globaluser and $globalpass) {
 | 
						|
        return { 'user' => $globaluser, 'pass' => $globalpass }
 | 
						|
    }
 | 
						|
    my $passtab = xCAT::Table->new('passwd',-create=>0);
 | 
						|
    my $passent = $passtab->getAttribs({key=>'svc'}, qw/username password/);
 | 
						|
    $globaluser = $passent->{username};
 | 
						|
    $globalpass = $passent->{password};
 | 
						|
   return { 'user' => $globaluser, 'pass' => $globalpass }
 | 
						|
}
 | 
						|
 | 
						|
sub establish_session {
 | 
						|
    my %args = @_;
 | 
						|
    my $controller = $args{controller};
 | 
						|
    if ($controllersessions{$controller}) {
 | 
						|
        return $controllersessions{$controller};
 | 
						|
    }
 | 
						|
    #need to establish a new session
 | 
						|
    my $cred = get_svc_creds($controller);
 | 
						|
    my $sess = new xCAT::SSHInteract(-username=>$cred->{user},
 | 
						|
                                     -password=>$cred->{pass},
 | 
						|
                                     -host=>$controller,
 | 
						|
                                     -output_record_separator=>"\r",
 | 
						|
                                     #Errmode=>"return",
 | 
						|
                                     #Input_Log=>"/tmp/svcdbgl",
 | 
						|
                                     Prompt=>'/>$/');
 | 
						|
    unless ($sess and $sess->atprompt) { die "TODO: cleanly handle bad login" }
 | 
						|
    $controllersessions{$controller} = $sess;
 | 
						|
    return $sess;
 | 
						|
}
 | 
						|
 | 
						|
sub create_lun {
 | 
						|
    my %args = @_;
 | 
						|
    my $session = establish_session(%args);
 | 
						|
    my $pool = $args{pool};
 | 
						|
    my $size = $args{size};
 | 
						|
    my $cmd="mkvdisk -iogrp io_grp0 -mdiskgrp $pool -size $size -unit gb";
 | 
						|
    if ($args{name}) {
 | 
						|
        $cmd .= " -name ".$args{name};
 | 
						|
    }
 | 
						|
    my @result = $session->cmd($cmd);
 | 
						|
    if ($result[0] =~ m/Virtual Disk, id \[(\d*)\], successfully created/) {
 | 
						|
        my $diskid = $1;
 | 
						|
        my $name;
 | 
						|
        my $wwn;
 | 
						|
        @result = $session->cmd("lsvdisk $diskid");
 | 
						|
        foreach (@result) {
 | 
						|
            chomp;
 | 
						|
            if (/^name (.*)\z/) {
 | 
						|
                $name = $1;
 | 
						|
            } elsif (/^vdisk_UID (.*)\z/) {
 | 
						|
                $wwn = $1;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        return { name => $name, id => $diskid, wwn => $wwn };
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
sub assure_identical_table_values {
 | 
						|
    my $nodes = shift;
 | 
						|
    my $storents = shift;
 | 
						|
    my $attribute = shift;
 | 
						|
    my $lastval;
 | 
						|
    foreach my $node (@$nodes) {
 | 
						|
        my $sent = $storents->{$node}->[0];
 | 
						|
        unless ($sent) {
 | 
						|
            sendmsg([1, "No $attribute in arguments or table"],
 | 
						|
                $callback, $node);
 | 
						|
            return undef;
 | 
						|
        }
 | 
						|
        my $currval = $sent->{$attribute};
 | 
						|
        unless ($currval) {
 | 
						|
            sendmsg([1, "No $attribute in arguments or table"],
 | 
						|
                $callback, $node);
 | 
						|
            return undef;
 | 
						|
        }
 | 
						|
        if ($lastval and $currval ne $lastval) {
 | 
						|
            sendmsg([1,
 | 
						|
                "$attribute mismatch in table config, try specifying as argument"],
 | 
						|
                $callback, $node);
 | 
						|
            return undef;
 | 
						|
        }
 | 
						|
        if (not defined $lastval) { $lastval = $currval; }
 | 
						|
    }
 | 
						|
    return $lastval;
 | 
						|
}
 | 
						|
 | 
						|
sub mkstorage_single {
 | 
						|
    my %args = @_;
 | 
						|
    my $size;
 | 
						|
    my $cfg = $args{cfg};
 | 
						|
    my $node = $args{node};
 | 
						|
    my $pool;
 | 
						|
    my $controller;
 | 
						|
    if (defined $args{size}) {
 | 
						|
        $size = $args{size};
 | 
						|
    } elsif ($cfg->{size}) {
 | 
						|
        $size = $cfg->{size};
 | 
						|
    } else {
 | 
						|
        sendmsg([1, "Size not provided via argument or storage.size"],
 | 
						|
            $callback, $node);
 | 
						|
    }
 | 
						|
    if (defined $args{pool}) {
 | 
						|
        $pool = $args{pool};
 | 
						|
    } elsif ($cfg->{storagepool}) {
 | 
						|
        $pool = $cfg->{storagepool};
 | 
						|
    } else {
 | 
						|
        sendmsg([1, "Pool not provided via argument or storage.storagepool"],
 | 
						|
            $callback, $node);
 | 
						|
    }
 | 
						|
    if (defined $args{controller}) {
 | 
						|
        $controller = $args{controller};
 | 
						|
    } elsif ($cfg->[0]->{controller}) {
 | 
						|
        $controller = $cfg->[0]->{controller};
 | 
						|
        $controller =~ s/.*,//;
 | 
						|
    }
 | 
						|
    my %lunargs = (controller=>$controller, size=>$size, pool=>$pool);
 | 
						|
    if ($args{name}) {
 | 
						|
        $lunargs{name} = $args{name}."-".$node;
 | 
						|
    }
 | 
						|
    my $lun = create_lun(%lunargs);
 | 
						|
    sendmsg($lun->{name}.": id: ".$lun->{wwn},$callback,$node);
 | 
						|
    my $wwns = get_wwns($node);
 | 
						|
    my %namemap = makehosts($wwns, controller=>$controller, cfg=>{$node=>$cfg});
 | 
						|
    my @names = values %namemap;
 | 
						|
    bindhosts(\@names, $lun, controller=>$controller);
 | 
						|
}
 | 
						|
 | 
						|
sub process_request {
 | 
						|
    my $request = shift;
 | 
						|
    $callback = shift;
 | 
						|
    $dorequest = shift;
 | 
						|
    if ($request->{command}->[0] eq 'mkstorage') {
 | 
						|
        mkstorage($request);
 | 
						|
    } elsif ($request->{command}->[0] eq 'lsstorage') {
 | 
						|
        lsstorage($request);
 | 
						|
    } elsif ($request->{command}->[0] eq 'rmstorage') {
 | 
						|
        rmstorage($request);
 | 
						|
    } elsif ($request->{command}->[0] eq 'detachstorage') {
 | 
						|
        detachstorage($request);
 | 
						|
    } elsif ($request->{command}->[0] eq 'lspool') {
 | 
						|
        lsmdiskgrp($request);
 | 
						|
    }
 | 
						|
    foreach (values %controllersessions) {
 | 
						|
        $_->close();
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
sub lsmdiskgrp {
 | 
						|
    my $req = shift;
 | 
						|
    foreach my $node (@{$req->{node}}) {
 | 
						|
        my $session = establish_session(controller=>$node);
 | 
						|
        my @pools = hashifyoutput($session->cmd("lsmdiskgrp -delim :"));
 | 
						|
        foreach my $pool (@pools) {
 | 
						|
            sendmsg($pool->{name}. " available capacity: ".$pool->{free_capacity},$callback,$node);
 | 
						|
            sendmsg($pool->{name}. " total capacity: ".$pool->{capacity},$callback,$node);
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
1;
 |