From 41ba3bb6985ae1b7b973aead4e14bb961e5659a3 Mon Sep 17 00:00:00 2001 From: sjing Date: Tue, 27 Dec 2011 03:35:48 +0000 Subject: [PATCH] lstree implementation. git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@11299 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd --- xCAT-server/lib/xcat/plugins/tree.pm | 655 +++++++++++++++++++++++++++ 1 file changed, 655 insertions(+) create mode 100644 xCAT-server/lib/xcat/plugins/tree.pm diff --git a/xCAT-server/lib/xcat/plugins/tree.pm b/xCAT-server/lib/xcat/plugins/tree.pm new file mode 100644 index 000000000..d4096741d --- /dev/null +++ b/xCAT-server/lib/xcat/plugins/tree.pm @@ -0,0 +1,655 @@ +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) + { + $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; + } + } + + 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;