mirror of
				https://github.com/xcat2/xcat-core.git
				synced 2025-10-31 03:12:30 +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;
 |