mirror of
				https://github.com/xcat2/xcat-core.git
				synced 2025-11-03 21:02:34 +00:00 
			
		
		
		
	git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@11754 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd
		
			
				
	
	
		
			661 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
			
		
		
	
	
			661 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
package xCAT_plugin::tree;
 | 
						|
 | 
						|
BEGIN
 | 
						|
{
 | 
						|
    $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat';
 | 
						|
}
 | 
						|
use lib "$::XCATROOT/lib/perl";
 | 
						|
 | 
						|
use xCAT::NodeRange;
 | 
						|
use Data::Dumper;
 | 
						|
use xCAT::Utils;
 | 
						|
use Sys::Syslog;
 | 
						|
use xCAT::GlobalDef;
 | 
						|
use xCAT::Table;
 | 
						|
use Getopt::Long;
 | 
						|
use xCAT::SvrUtils;
 | 
						|
#use strict;
 | 
						|
 | 
						|
sub handled_commands
 | 
						|
{
 | 
						|
    # currently, only for lstree command.
 | 
						|
    return {
 | 
						|
        lstree => "tree",
 | 
						|
    };
 | 
						|
}
 | 
						|
 | 
						|
sub usage
 | 
						|
{
 | 
						|
    my $command = shift;
 | 
						|
    my $callback = shift;
 | 
						|
 | 
						|
    if($command eq "lstree")
 | 
						|
    {
 | 
						|
        &usage_lstree($callback);
 | 
						|
        return 0;
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        return 1;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
#----------------------------------------------------------------------------
 | 
						|
 | 
						|
=head3  usage_lstree
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
#-----------------------------------------------------------------------------
 | 
						|
sub usage_lstree
 | 
						|
{
 | 
						|
    my $callback = shift;
 | 
						|
 | 
						|
    my $rsp;
 | 
						|
    push @{$rsp->{data}},
 | 
						|
      "\n  lstree - Display the tree of service node hierarchy, hardware hierarchy, or VM hierarchy.";
 | 
						|
    push @{$rsp->{data}}, "  Usage: ";
 | 
						|
    push @{$rsp->{data}}, "\tlstree [-h | --help]";
 | 
						|
    push @{$rsp->{data}}, "or";
 | 
						|
    push @{$rsp->{data}}, "\tlstree [-s | --servicenode] [-H | --hardwaremgmt] [-v | --virtualmachine] [noderange]";
 | 
						|
    
 | 
						|
    xCAT::MsgUtils->message("I", $rsp, $callback);
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
#----------------------------------------------------------------------------
 | 
						|
 | 
						|
=head3  process_request
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
#-----------------------------------------------------------------------------
 | 
						|
sub process_request
 | 
						|
{
 | 
						|
    my $request = shift;
 | 
						|
    my $callback = shift;
 | 
						|
    my @nodes=();
 | 
						|
 | 
						|
    if($request->{node})
 | 
						|
    {
 | 
						|
        @nodes = @{$request->{node}};
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        # handle all nodes by default.
 | 
						|
        my $nodelist = xCAT::Table->new('nodelist');
 | 
						|
        unless ($nodelist)
 | 
						|
        {
 | 
						|
            my $rsp = {};
 | 
						|
            $rsp->{data}->[0] = "Can not open nodelist table.\n";
 | 
						|
            xCAT::MsgUtils->message("E", $rsp, $callback, 1);
 | 
						|
        }
 | 
						|
 | 
						|
        my @entries  = ($nodelist->getAllNodeAttribs([qw(node)]));
 | 
						|
        foreach (@entries)
 | 
						|
        {
 | 
						|
            push @nodes, $_->{node};
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    my $command = $request->{command}->[0];
 | 
						|
    if($command eq "lstree")
 | 
						|
    {
 | 
						|
        &lstree($request, $callback, \@nodes);
 | 
						|
        return 0;
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        $callback->({error=>["error in code..."], errorcode=>[127]});
 | 
						|
        $request = {};
 | 
						|
        return 0;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
#----------------------------------------------------------------------------
 | 
						|
 | 
						|
=head3  lstree
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
#-----------------------------------------------------------------------------
 | 
						|
sub lstree
 | 
						|
{
 | 
						|
    my $request = shift;
 | 
						|
    my $callback = shift;
 | 
						|
    my $nodelist = shift;
 | 
						|
 | 
						|
    unless($request->{arg} || defined $nodelist)
 | 
						|
    {
 | 
						|
        &usage_lstree($callback);
 | 
						|
        return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    # parse the options
 | 
						|
    Getopt::Long::Configure("no_pass_through");
 | 
						|
    Getopt::Long::Configure("bundling");
 | 
						|
    
 | 
						|
    if ($request->{arg})
 | 
						|
    {
 | 
						|
        @ARGV = @{$request->{arg}};
 | 
						|
        
 | 
						|
        if (
 | 
						|
            !GetOptions(
 | 
						|
                        'h|help'           => \$::HELP,
 | 
						|
                        's|servicenode'    => \$::SVCNODE,
 | 
						|
                        'H|hardwaremgmt'   => \$::HDWR,
 | 
						|
                        'v|virtualmachine' => \$::VMACHINE,
 | 
						|
            )
 | 
						|
          )
 | 
						|
        {
 | 
						|
            &usage_lstree($callback);
 | 
						|
            return 1;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    if ($::HELP)
 | 
						|
    {
 | 
						|
        &usage_lstree($callback);
 | 
						|
        return 0;
 | 
						|
    }
 | 
						|
 | 
						|
    if (!$::SVCNODE && !$::HDWR && !$::VMACHINE)
 | 
						|
    {
 | 
						|
        # show both vmtree and hwtree by default.
 | 
						|
        $::SHOWALL = 1;
 | 
						|
    }
 | 
						|
 | 
						|
    my %hwtrees;
 | 
						|
    my %vmtrees;
 | 
						|
    my %sntrees;
 | 
						|
    
 | 
						|
    # servicenode hierarchy
 | 
						|
    if ($::SVCNODE)
 | 
						|
    {
 | 
						|
        # build up sn tree hash.
 | 
						|
        my $snhash;
 | 
						|
        my @entries;
 | 
						|
        my $restab = xCAT::Table->new('noderes');
 | 
						|
        if ($restab)
 | 
						|
        {
 | 
						|
            $snhash = $restab->getNodesAttribs($nodelist, ['servicenode']);
 | 
						|
            @entries = $restab->getAllNodeAttribs(['node','servicenode']);
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            my $rsp = {};
 | 
						|
            $rsp->{data}->[0] = "Can not open noderes table.\n";
 | 
						|
            xCAT::MsgUtils->message("E", $rsp, $callback, 1);
 | 
						|
        }
 | 
						|
 | 
						|
        foreach my $node (@$nodelist)
 | 
						|
        {
 | 
						|
            # servicenode defined for this node
 | 
						|
            if ($snhash->{$node}->[0]->{'servicenode'})
 | 
						|
            {
 | 
						|
                unless (grep(/$node/, @{$sntrees{$snhash->{$node}->[0]->{'servicenode'}}}))
 | 
						|
                {
 | 
						|
                    push @{$sntrees{$snhash->{$node}->[0]->{'servicenode'}}}, $node;
 | 
						|
                }
 | 
						|
            }
 | 
						|
            else # need to know if itself is service node
 | 
						|
            {
 | 
						|
                foreach my $ent (@entries)
 | 
						|
                {
 | 
						|
                    if ($ent->{servicenode} eq $node)
 | 
						|
                    {
 | 
						|
                        unless (grep(/$ent->{node}/, @{$sntrees{$node}}))
 | 
						|
                        {
 | 
						|
                            push @{$sntrees{$node}}, $ent->{node};
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
        
 | 
						|
        }
 | 
						|
        #print Dumper(\%sntreehash);
 | 
						|
 | 
						|
        # show service node tree
 | 
						|
        &showtree(\%sntrees, 0, 0, $callback);
 | 
						|
    }    
 | 
						|
 | 
						|
    # get hwtree hash from each plugin
 | 
						|
    if ($::HDWR || $::SHOWALL)
 | 
						|
    {
 | 
						|
        # classify the nodes
 | 
						|
        # read nodehm.mgt
 | 
						|
        my $hmhash;
 | 
						|
        my $hmtab = xCAT::Table->new('nodehm');
 | 
						|
        if ($hmtab)
 | 
						|
        {
 | 
						|
            $hmhash = $hmtab->getNodesAttribs($nodelist, ['mgt']);
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            my $rsp = {};
 | 
						|
            $rsp->{data}->[0] = "Can not open nodehm table.\n";
 | 
						|
            xCAT::MsgUtils->message("E", $rsp, $callback, 1);
 | 
						|
        }
 | 
						|
 | 
						|
        # may add new support later.
 | 
						|
        my @supportedhw = ("hmc", "fsp", "blade", "ipmi");
 | 
						|
        my %hwnodes;
 | 
						|
 | 
						|
        foreach my $node (@$nodelist)
 | 
						|
        {
 | 
						|
            # mgt defined for this node
 | 
						|
            unless ($hmhash->{$node}->[0]->{'mgt'})
 | 
						|
            {
 | 
						|
                next;
 | 
						|
            }
 | 
						|
 | 
						|
            if (grep(/$hmhash->{$node}->[0]->{'mgt'}/, @supportedhw))
 | 
						|
            {
 | 
						|
                push @{$hwnodes{$hmhash->{$node}->[0]->{'mgt'}}}, $node;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        if (%hwnodes)
 | 
						|
        {
 | 
						|
            foreach my $type (keys %hwnodes)
 | 
						|
            {
 | 
						|
                eval "require xCAT_plugin::$type";
 | 
						|
                $hwtrees{$type} = ${"xCAT_plugin::".$type."::"}{genhwtree}->(\@{$hwnodes{$type}}, $callback);
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        #print Dumper(\%hwtrees);
 | 
						|
    }
 | 
						|
 | 
						|
    if ($::HDWR && !$::VMACHINE)
 | 
						|
    {
 | 
						|
        &showtree(0, \%hwtrees, 0, $callback);
 | 
						|
    }
 | 
						|
 | 
						|
    # generate vmtree from xcat vm table
 | 
						|
    if ($::VMACHINE || $::SHOWALL)
 | 
						|
    {
 | 
						|
 | 
						|
        # here is a special case for zvm.
 | 
						|
        ########### start ################
 | 
						|
        # read nodehm.mgt
 | 
						|
        my $hmhash;
 | 
						|
        my $hmtab = xCAT::Table->new('nodehm');
 | 
						|
        if ($hmtab)
 | 
						|
        {
 | 
						|
            $hmhash = $hmtab->getNodesAttribs($nodelist, ['mgt']);
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            my $rsp = {};
 | 
						|
            $rsp->{data}->[0] = "Can not open nodehm table.\n";
 | 
						|
            xCAT::MsgUtils->message("E", $rsp, $callback, 1);
 | 
						|
        }
 | 
						|
 | 
						|
        my @znodes;
 | 
						|
 | 
						|
        foreach my $node (@$nodelist)
 | 
						|
        {
 | 
						|
            # mgt defined for this node
 | 
						|
            unless ($hmhash->{$node}->[0]->{'mgt'})
 | 
						|
            {
 | 
						|
                next;
 | 
						|
            }
 | 
						|
 | 
						|
            if ($hmhash->{$node}->[0]->{'mgt'} =~ /zvm/)
 | 
						|
            {
 | 
						|
                push @znodes, $node;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        if (scalar @znodes)
 | 
						|
        {
 | 
						|
         eval "require xCAT_plugin::zvm";
 | 
						|
         my $ret = xCAT_plugin::zvm::listTree($callback, \@znodes);
 | 
						|
        }
 | 
						|
        
 | 
						|
        ########### end ################
 | 
						|
        
 | 
						|
        # read vm.host
 | 
						|
        my $vmhash;
 | 
						|
        
 | 
						|
        my $vmtab = xCAT::Table->new('vm');
 | 
						|
        if ($vmtab)
 | 
						|
        {
 | 
						|
            $vmhash = $vmtab->getNodesAttribs($nodelist, ['host']);
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            my $rsp = {};
 | 
						|
            $rsp->{data}->[0] = "Can not open vm table.\n";
 | 
						|
            xCAT::MsgUtils->message("E", $rsp, $callback, 1);
 | 
						|
        }
 | 
						|
 | 
						|
        my @entries = $vmtab->getAllNodeAttribs(['node','host']);
 | 
						|
        
 | 
						|
        foreach my $node (@$nodelist)
 | 
						|
        {
 | 
						|
            foreach my $ent (@entries)
 | 
						|
            {
 | 
						|
                if ($ent->{host} =~ /$node/) # host
 | 
						|
                {
 | 
						|
                    push @{$vmtrees{$node}}, $ent->{node};
 | 
						|
                }
 | 
						|
            }
 | 
						|
            
 | 
						|
            if ($vmhash && $vmhash->{$node}->[0]->{'host'}) # vm
 | 
						|
            {
 | 
						|
                unless (grep(/$node/, @{$vmtrees{$vmhash->{$node}->[0]->{'host'}}}))
 | 
						|
                {
 | 
						|
                    push @{$vmtrees{$vmhash->{$node}->[0]->{'host'}}}, $node;
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }        
 | 
						|
        #print Dumper(\%vmtrees);
 | 
						|
    }
 | 
						|
 | 
						|
    # vm tree output
 | 
						|
    if (!$::HDWR && $::VMACHINE)
 | 
						|
    {
 | 
						|
        &showtree(0, 0, \%vmtrees, $callback);
 | 
						|
    }
 | 
						|
 | 
						|
    if ($::SHOWALL || ($::HDWR && $::VMACHINE))
 | 
						|
    {
 | 
						|
        &showtree(0, \%hwtrees, \%vmtrees, $callback);
 | 
						|
    }
 | 
						|
    return;
 | 
						|
 | 
						|
} # lstree end
 | 
						|
 | 
						|
#----------------------------------------------------------------------------
 | 
						|
 | 
						|
=head3  showtree
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
#-----------------------------------------------------------------------------
 | 
						|
sub showtree
 | 
						|
{
 | 
						|
    my $snthash = shift;
 | 
						|
    my $hwthash = shift;
 | 
						|
    my $vmthash = shift;
 | 
						|
    my $callback = shift;
 | 
						|
 | 
						|
    my %sntrees = %$snthash;
 | 
						|
    my %hwtrees = %$hwthash;
 | 
						|
    my %vmtrees = %$vmthash;
 | 
						|
 | 
						|
    # temp workaround before we integrate LPARs into vm table
 | 
						|
    my $lparinvm = 0;
 | 
						|
    my @entries;
 | 
						|
 | 
						|
    if (!$lparinvm)
 | 
						|
    {
 | 
						|
        # read ppc table
 | 
						|
        my $ppctab = xCAT::Table->new('ppc');
 | 
						|
        unless ($ppctab)
 | 
						|
        {
 | 
						|
            my $rsp = {};
 | 
						|
            $rsp->{data}->[0] = "Can not open ppc table.\n";
 | 
						|
            xCAT::MsgUtils->message("E", $rsp, $callback, 1);
 | 
						|
        }
 | 
						|
 | 
						|
        @entries = $ppctab->getAllNodeAttribs(['node','id','parent']);    
 | 
						|
    }
 | 
						|
 | 
						|
    if (%sntrees)
 | 
						|
    {
 | 
						|
        my $rsp;
 | 
						|
 | 
						|
        foreach my $sn (sort(keys %sntrees))
 | 
						|
        {
 | 
						|
            push @{$rsp->{data}}, "Service Node: $sn";
 | 
						|
            foreach my $cn (sort(@{$sntrees{$sn}}))
 | 
						|
            {
 | 
						|
                push @{$rsp->{data}}, "|__$cn";
 | 
						|
            }
 | 
						|
            push @{$rsp->{data}}, 
 | 
						|
"\n";
 | 
						|
        }
 | 
						|
        xCAT::MsgUtils->message("I", $rsp, $callback);  
 | 
						|
    }
 | 
						|
 | 
						|
    # show hardware hierarchy
 | 
						|
    if (%hwtrees)    
 | 
						|
    {
 | 
						|
        my $rsp;
 | 
						|
 | 
						|
        # hmc tree output
 | 
						|
        foreach my $hmc (sort(keys %{$hwtrees{hmc}}))
 | 
						|
        {
 | 
						|
            push @{$rsp->{data}}, "HMC: $hmc";
 | 
						|
            foreach my $frame (sort(keys %{$hwtrees{hmc}{$hmc}}))
 | 
						|
            {
 | 
						|
                if ($frame eq '0')
 | 
						|
                {
 | 
						|
                    # no frame
 | 
						|
                    push @{$rsp->{data}}, "|__Frame: n/a";
 | 
						|
                }
 | 
						|
                else
 | 
						|
                {
 | 
						|
                    # get bpas for frame.
 | 
						|
                    my $bpas = xCAT::DBobjUtils->getchildren($frame);
 | 
						|
                    my $bpalist = join ',', @$bpas; 
 | 
						|
                    push @{$rsp->{data}}, "|__Frame: $frame $bpalist";
 | 
						|
                }
 | 
						|
                
 | 
						|
                foreach my $cec (sort @{$hwtrees{hmc}{$hmc}{$frame}})
 | 
						|
                {
 | 
						|
 | 
						|
                    # get fsps for cec.
 | 
						|
                    my $fsps = xCAT::DBobjUtils->getchildren($cec);
 | 
						|
                    my $fsplist = join ',', @$fsps; 
 | 
						|
                    push @{$rsp->{data}}, "   |__CEC: $cec $fsplist";
 | 
						|
 | 
						|
                    if ($lparinvm)
 | 
						|
                    {
 | 
						|
                        # if show both, tailing with vmtree.
 | 
						|
                        if (%vmtrees)
 | 
						|
                        {
 | 
						|
                            foreach my $host (sort(keys %vmtrees))
 | 
						|
                            {
 | 
						|
                                if ($host =~ /$cec/)
 | 
						|
                                {
 | 
						|
                                    foreach my $vm (sort(@{$vmtrees{$host}}))
 | 
						|
                                    {
 | 
						|
                                        push @{$rsp->{data}}, "      |__ $vm";
 | 
						|
                                    }
 | 
						|
 | 
						|
                                    # remove it as shown
 | 
						|
                                    undef $vmtrees{$host};
 | 
						|
                                }
 | 
						|
                            }
 | 
						|
                        }                    
 | 
						|
                    }
 | 
						|
                    elsif ($::VMACHINE || $::SHOWALL) # temp workaround before we integrate LPARs into vm table
 | 
						|
                    {
 | 
						|
                        my %vm;
 | 
						|
                        # get all lpars in this cec.
 | 
						|
                        foreach my $ent (@entries)
 | 
						|
                        {
 | 
						|
                            if ($ent->{parent} =~ /$cec/)
 | 
						|
                            {
 | 
						|
                                $vm{$ent->{id}} = $ent->{node};
 | 
						|
                            }
 | 
						|
                        }
 | 
						|
 | 
						|
                        foreach my $id (sort(keys %vm))
 | 
						|
                        {
 | 
						|
                            push @{$rsp->{data}}, "      |__LPAR $id: $vm{$id}";
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
            push @{$rsp->{data}}, "\n";
 | 
						|
        }
 | 
						|
 | 
						|
        # DFM tree output
 | 
						|
        foreach my $sfp (sort(keys %{$hwtrees{fsp}}))
 | 
						|
        {
 | 
						|
            if ($sfp eq '0')
 | 
						|
            {
 | 
						|
                # no frame
 | 
						|
                push @{$rsp->{data}}, "Service Focal Point: n/a";
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
                push @{$rsp->{data}}, "Service Focal Point: $sfp";
 | 
						|
            }
 | 
						|
 | 
						|
            foreach my $frame (sort(keys %{$hwtrees{fsp}{$sfp}}))
 | 
						|
            {
 | 
						|
                if ($frame eq '0')
 | 
						|
                {
 | 
						|
                    # no frame
 | 
						|
                    push @{$rsp->{data}}, "|__Frame: n/a";
 | 
						|
                }
 | 
						|
                else
 | 
						|
                {
 | 
						|
                    # get bpas for frame.
 | 
						|
                    my $bpas = xCAT::DBobjUtils->getchildren($frame);
 | 
						|
                    my $bpalist = join ',', @$bpas; 
 | 
						|
                    push @{$rsp->{data}}, "|__Frame: $frame $bpalist";
 | 
						|
                }
 | 
						|
                
 | 
						|
                foreach my $cec (sort @{$hwtrees{fsp}{$sfp}{$frame}})
 | 
						|
                {
 | 
						|
 | 
						|
                    # get fsps for cec.
 | 
						|
                    my $fsps = xCAT::DBobjUtils->getchildren($cec);
 | 
						|
                    my $fsplist = join ',', @$fsps; 
 | 
						|
                    push @{$rsp->{data}}, "   |__CEC: $cec $fsplist";
 | 
						|
 | 
						|
                    if ($lparinvm)
 | 
						|
                    {
 | 
						|
                        # if show both, tailing with vmtree.
 | 
						|
                        if (%vmtrees)
 | 
						|
                        {
 | 
						|
                            foreach my $host (sort(keys %vmtrees))
 | 
						|
                            {
 | 
						|
                                if ($host =~ /$cec/)
 | 
						|
                                {
 | 
						|
                                    foreach my $vm (sort(@{$vmtrees{$host}}))
 | 
						|
                                    {
 | 
						|
                                        push @{$rsp->{data}}, "      |__ $vm";
 | 
						|
                                    }
 | 
						|
                                    # remove it as shown
 | 
						|
                                    undef $vmtrees{$host};                                
 | 
						|
                                }
 | 
						|
                            }
 | 
						|
                        }                    
 | 
						|
                    }
 | 
						|
                    elsif ($::VMACHINE || $::SHOWALL) # temp workaround before we integrate LPARs into vm table
 | 
						|
                    {
 | 
						|
                        my %vm;
 | 
						|
                        # get all lpars in this cec.
 | 
						|
                        foreach my $ent (@entries)
 | 
						|
                        {
 | 
						|
                            if ($ent->{parent} =~ /$cec/)
 | 
						|
                            {
 | 
						|
                                $vm{$ent->{id}} = $ent->{node};
 | 
						|
                            }
 | 
						|
                        }
 | 
						|
 | 
						|
                        foreach my $id (sort(keys %vm))
 | 
						|
                        {
 | 
						|
                            push @{$rsp->{data}}, "      |__LPAR $id: $vm{$id}";
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
            push @{$rsp->{data}}, "\n";
 | 
						|
        }
 | 
						|
 | 
						|
        # blade tree output
 | 
						|
        foreach my $mm (sort(keys %{$hwtrees{blade}}))
 | 
						|
        {
 | 
						|
            push @{$rsp->{data}}, "Management Module: $mm";
 | 
						|
 | 
						|
            foreach my $slot (sort(keys %{$hwtrees{blade}{$mm}}))
 | 
						|
            {
 | 
						|
                my $blade = $hwtrees{blade}{$mm}{$slot};
 | 
						|
                push @{$rsp->{data}}, "|__Blade $slot: $blade"; 
 | 
						|
 | 
						|
                # if show both, tailing with vmtree.
 | 
						|
                if (%vmtrees)
 | 
						|
                {
 | 
						|
                    foreach my $host (sort(keys %vmtrees))
 | 
						|
                    {
 | 
						|
                        if ($host =~ /$blade/)
 | 
						|
                        {
 | 
						|
                            foreach my $vm (sort(@{$vmtrees{$host}}))
 | 
						|
                            {
 | 
						|
                                push @{$rsp->{data}}, "   |__ $vm";
 | 
						|
                            }
 | 
						|
                            # remove it as shown
 | 
						|
                            undef $vmtrees{$host};                            
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
            push @{$rsp->{data}}, "\n";
 | 
						|
        }
 | 
						|
 | 
						|
        # ipmi tree output
 | 
						|
        foreach my $bmc (sort(keys %{$hwtrees{ipmi}}))
 | 
						|
        {
 | 
						|
            push @{$rsp->{data}}, "BMC: $bmc";
 | 
						|
            foreach my $svr (sort(@{$hwtrees{ipmi}{$bmc}}))
 | 
						|
            {
 | 
						|
                push @{$rsp->{data}}, "|__Server: $svr";
 | 
						|
 | 
						|
                # if show both, tailing with vmtree.
 | 
						|
                if (%vmtrees)
 | 
						|
                {
 | 
						|
                    foreach my $host (sort(keys %vmtrees))
 | 
						|
                    {
 | 
						|
                        if ($host =~ /$svr/)
 | 
						|
                        {
 | 
						|
                            foreach my $vm (sort(@{$vmtrees{$host}}))
 | 
						|
                            {
 | 
						|
                                push @{$rsp->{data}}, "   |__ $vm";
 | 
						|
                            }
 | 
						|
                            # remove it as shown
 | 
						|
                            undef $vmtrees{$host};                            
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                }                
 | 
						|
            }
 | 
						|
            push @{$rsp->{data}}, "\n";
 | 
						|
        }        
 | 
						|
        
 | 
						|
        xCAT::MsgUtils->message("I", $rsp, $callback);                    
 | 
						|
    }    
 | 
						|
 | 
						|
    # show VM hierarchy
 | 
						|
    if (%vmtrees)
 | 
						|
    {
 | 
						|
        my $rsp;
 | 
						|
        foreach my $host (sort(keys %vmtrees))
 | 
						|
        {
 | 
						|
            if (defined $vmtrees{$host})
 | 
						|
            {
 | 
						|
                push @{$rsp->{data}}, "Server: $host";
 | 
						|
                foreach my $vm (sort(@{$vmtrees{$host}}))
 | 
						|
                {
 | 
						|
                    push @{$rsp->{data}}, "|__ $vm";
 | 
						|
                }
 | 
						|
            }
 | 
						|
            push @{$rsp->{data}}, "\n";
 | 
						|
        }
 | 
						|
        xCAT::MsgUtils->message("I", $rsp, $callback);
 | 
						|
        
 | 
						|
    }
 | 
						|
    
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
1;
 |