mirror of
				https://github.com/xcat2/xcat-core.git
				synced 2025-10-31 11:22:27 +00:00 
			
		
		
		
	Merge pull request #452 from hu-weihua/getadapters
Cool. Will merge it, eventually.
This commit is contained in:
		
							
								
								
									
										53
									
								
								docs/source/advanced/networks/getadapters.rst
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										53
									
								
								docs/source/advanced/networks/getadapters.rst
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,53 @@ | ||||
| Predict network adapter name before deployment | ||||
| ============================================== | ||||
|  | ||||
|  | ||||
|  | ||||
| Traditionally, network interfaces in Linux are enumerated as eth[0123…], but these names do not necessarily correspond to actual labels on the chassis. customer need a methods to get consistent and predictable network device name before provision or network configuration. xCAT provide a tool ``getadapters`` to help customer to resolve this problem. | ||||
|  | ||||
|  | ||||
| **[Note]** : This feature needs to restart your target sever which you want to obtain network adapter from. | ||||
|  | ||||
| How to use get adapters | ||||
| ----------------------- | ||||
|  | ||||
|  | ||||
| Using below command to obtain the network adapters information :: | ||||
|   | ||||
|     getadapters <noderange> | ||||
|  | ||||
| Then will get output like below :: | ||||
|  | ||||
|  | ||||
|     The whole scan result: | ||||
|     -------------------------------------- | ||||
|     node1:1:hitname=enP3p3s0f0|pci=/pci0003:00/0003:00:00.0/0003:01:00.0/0003:02:01.0/0003:03:00.0|mac=98be9459ea24|candidatename=enP3p3s0f0,enx98be9459ea24|vendor=Broadcom Corporation|modle=NetXtreme II BCM57800 1/10 Gigabit Ethernet | ||||
|     node1:2:hitname=enP3p3s0f1|pci=/pci0003:00/0003:00:00.0/0003:01:00.0/0003:02:01.0/0003:03:00.1|mac=98be9459ea25|candidatename=enP3p3s0f1,enx98be9459ea25|vendor=Broadcom Corporation|modle=NetXtreme II BCM57800 1/10 Gigabit Ethernet | ||||
|     node1:3:hitname=enP3p3s0f2|pci=/pci0003:00/0003:00:00.0/0003:01:00.0/0003:02:01.0/0003:03:00.2|mac=98be9459ea26|candidatename=enP3p3s0f2,enx98be9459ea26|vendor=Broadcom Corporation|modle=NetXtreme II BCM57800 1/10 Gigabit Ethernet | ||||
|     node1:4:hitname=enP3p3s0f3|pci=/pci0003:00/0003:00:00.0/0003:01:00.0/0003:02:01.0/0003:03:00.3|mac=98be9459ea27|candidatename=enP3p3s0f3,enx98be9459ea27|vendor=Broadcom Corporation|modle=NetXtreme II BCM57800 1/10 Gigabit Ethernet | ||||
|     node1:5:pci=0001:01:00.0|modle=Mellanox Technologies MT27600 [Connect-IB] | ||||
|     -------------------------------------- | ||||
|     node2:1:hitname=enP3p3s0f0|pci=/pci0003:00/0003:00:00.0/0003:01:00.0/0003:02:01.0/0003:03:00.0|mac=98be9459ea24|candidatename=enP3p3s0f0,enx98be9459ea24|vendor=Broadcom Corporation|modle=NetXtreme II BCM57800 1/10 Gigabit Ethernet | ||||
|     node2:2:hitname=enP3p3s0f1|pci=/pci0003:00/0003:00:00.0/0003:01:00.0/0003:02:01.0/0003:03:00.1|mac=98be9459ea25|candidatename=enP3p3s0f1,enx98be9459ea25|vendor=Broadcom Corporation|modle=NetXtreme II BCM57800 1/10 Gigabit Ethernet | ||||
|  | ||||
|  | ||||
| Every node gets a separate section to display its all network adapters information, every network adapter owns single line which start as node name and followed by index and other information. | ||||
|  | ||||
| xCAT try its best to collect more information for each network adapter, but can’t guarantee collect same much information for every one. If a network adapter can be derived by xcat genesis, this adapter will have a predictable name, if it can’t be, it only has the information xcat can obtain. | ||||
|      | ||||
| below are the possible information: | ||||
|  | ||||
| * **hitname**: the consistent name which can be used in ``confignic`` derectly in operating system which follow the same naming scheme with rhels7. (``confignic`` doesn’t need to do more work) | ||||
|  | ||||
| * **pci**: the pci location | ||||
|  | ||||
| * **mac**: the MAC address | ||||
|  | ||||
| * **candidatename**: All the names which satisfy predictable network device naming scheme, if customer needs to customize their network adapter name, they can choose one of them. (``confignic`` needs to do more work to support this. if customer want to use their own name, xcat should offer a interface to get customer’s input and change this column)  | ||||
|  | ||||
| * **vendor**:  the vender of network device | ||||
|  | ||||
| * **modle**:  the modle of network device | ||||
|      | ||||
|      | ||||
|      | ||||
							
								
								
									
										85
									
								
								xCAT-client/pods/man1/getadapters.1.pod
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								xCAT-client/pods/man1/getadapters.1.pod
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,85 @@ | ||||
| =head1 NAME | ||||
|  | ||||
| B<getadapters> - Obtain all network adapters's predictable name and some other information before provision or network configuration. | ||||
|  | ||||
| =head1 SYNOPSIS | ||||
|  | ||||
| B<getadapters> I<noderange> [B<-f>] | ||||
|  | ||||
| B<getadapters> [B<-h>|B<--help>|B<-v>|B<--version>|B<-V>] | ||||
|  | ||||
| =head1 DESCRIPTION | ||||
|  | ||||
| Traditionally, network interfaces in Linux are enumerated as eth[0123<32>], but these names do not necessarily correspond to actual labels on the chassis. B<getadapters> help customer to get predictable network device name and some other network adapter information before provision or network configuration. | ||||
|  | ||||
| B<getadapters> use genesis to collect network adapters information, so that mean it need to restart the target node. | ||||
|  | ||||
| B<getadapters> follows below scheme: | ||||
|  | ||||
| If the target node is scaned for the first time, B<getadapters> will trigger genesis to collect information then save the information at local.  | ||||
| If the target node has ever been scaned, i.e. this node has network device information in local, B<getadapters> use the local information first. | ||||
| If user doesn't want to use local information, can use B<-f> option to force to trigger new round scan process. | ||||
| if part nodes of I<noderange> don't have network device information in local and the rest have, B<getadapters> only trigger real scan process for these nodes which don't have local information, the nodes have network device information in local, B<getadapters> still use the local information first. | ||||
|  | ||||
| B<getadapters> tries to collect more information for the  target network device,  but doesn't guarantee collect same much information for every network device. | ||||
|  | ||||
| Below are the possible information can be collect up to now: | ||||
| B<hitname>: the consistent name which can be used by confignic directly in operating system which follow the same naming scheme with rhels7 | ||||
| B<pci>: the pci location | ||||
| B<mac>: the MAC address | ||||
| B<candidatename>: All the names which satisfy predictable network device naming scheme. I<(if xcat enhance confignic command later, user can use these names to configure their network adapter, even customize their name)> | ||||
| B<vender>:  the vender of network device | ||||
| B<model>:  the model of network device | ||||
|  | ||||
| =head1 OPTIONS | ||||
|  | ||||
| B<-h>           | ||||
|  | ||||
| Display usage message. | ||||
|  | ||||
| B<-v>           | ||||
|  | ||||
| Command Version. | ||||
|  | ||||
| B<-V>           | ||||
|  | ||||
| Display verbose message. | ||||
|  | ||||
| B<-f> | ||||
|  | ||||
| Force to trigger new round scan. ignore the data collected before. | ||||
|  | ||||
|  | ||||
| =head1 EXAMPLES | ||||
|  | ||||
| 1. To collect node[1-3]'s network device information, enter: | ||||
|   | ||||
|  getadapters  node[1-2] | ||||
|  | ||||
| Output is similar to: | ||||
|  | ||||
| -->Starting scan for: node1,node2 | ||||
| The whole scan result: | ||||
| -------------------------------------- | ||||
| [node1] with no need for scan due to old data exist, using the old data: | ||||
| node1:1:mac=98be9459ea24|pci=/0003:03:00.0|candidatename=enx98be9459ea24|vender=Broadcom Corporation  | ||||
| node1:2:mac=98be9459ea25|pci=/0003:03:00.1|candidatename=enx98be9459ea25|vender=Broadcom Corporation | ||||
| -------------------------------------- | ||||
| [node2] scan successfully, below are the latest data | ||||
| node2:1:mac=98be9459ea34|pci=/0003:03:00.0|candidatename=enx98be9459ea34|vender=Broadcom Corporation  | ||||
| node2:2:mac=98be9459ea35|pci=/0003:03:00.1|candidatename=enx98be9459ea35|vender=Broadcom Corporation | ||||
|  | ||||
| Every node gets a separate section to display its all network adapters information, every network adapter owns single line which start as node name and followed by index and other information. | ||||
|  | ||||
|  | ||||
| 2. Force to trigger new round scan | ||||
|  | ||||
|   getadatpers node -f | ||||
|  | ||||
|  | ||||
|  | ||||
| =head1 SEE ALSO | ||||
|  | ||||
| L<noderange(3)|noderange.3>  | ||||
|  | ||||
|  | ||||
							
								
								
									
										112
									
								
								xCAT-genesis-scripts/bin/getadapter
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										112
									
								
								xCAT-genesis-scripts/bin/getadapter
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,112 @@ | ||||
| #!/bin/bash | ||||
| #set -x | ||||
|  | ||||
| XCATPORT=3001 | ||||
| export XCATPORT | ||||
|  | ||||
| #XCATMASTER="10.3.5.21" | ||||
| ADAPTERFILE="/tmp/adapterinfo" | ||||
| SCANNICLOG="/tmp/adapterscan.log" | ||||
|  | ||||
| rm -f "$SCANNICLOG" >/dev/null 2>&1  | ||||
|  | ||||
| if [ -f "$ADAPTERFILE" ]; then | ||||
|     echo "rm -f $ADAPTERFILE" > "$SCANNICLOG" | ||||
|     rm -f "$ADAPTERFILE" >> "$SCANNICLOG"  2>&1 | ||||
| fi | ||||
|  | ||||
| echo "<xcatrequest> | ||||
| <command>findadapter</command> | ||||
| <clienttype>cli</clienttype> | ||||
| <hostname>$HOSTNAME</hostname>"  >> "$ADAPTERFILE" | ||||
|  | ||||
| #scan adapters have recognized by operating system | ||||
| for n in /sys/class/net/*; do | ||||
|     nic=${n##/sys/class/net/} | ||||
|     if [ "$nic" == "lo" ]; then | ||||
|         continue | ||||
|     else | ||||
|         echo '<nic>' >> "$ADAPTERFILE" | ||||
|         tmp=`udevadm info /sys/class/net/"$nic" | grep " INTERFACE" | awk -F '=' '{print $2}'` | ||||
|         if [ -n "$tmp" ]; then | ||||
|             echo "<interface>$tmp</interface>" >> "$ADAPTERFILE" | ||||
|         fi | ||||
|         tmp=`udevadm info /sys/class/net/"$nic" | grep ID_NET_NAME | awk -F '=' '{print $2}'|sort -u| tr -s "\n" "," | sed "s/,$//g"` | ||||
|         if [ -n "$tmp" ]; then | ||||
|             echo "<predictablename>$tmp</predictablename>" >> "$ADAPTERFILE" | ||||
|         fi | ||||
|         tmp=`udevadm info /sys/class/net/"$nic" | grep DEVPATH | awk -F 'devices' '{print $2}'` | ||||
|         if [ -n "$tmp" ]; then | ||||
|             echo "<pcilocation>${tmp%/net*}</pcilocation>" >> "$ADAPTERFILE" | ||||
|         fi | ||||
|         tmp=`udevadm info /sys/class/net/"$nic" | grep ID_NET_NAME_MAC | awk -F '=' '{print $2}'` | ||||
|         if [ -n "$tmp" ]; then | ||||
|             echo "<mac>${tmp##*enx}</mac>" >> "$ADAPTERFILE" | ||||
|         fi | ||||
|         tmp=`udevadm info /sys/class/net/"$nic" | grep ID_VENDOR_FROM_DATABASE | awk -F '=' '{print $2}' | tr -s "\n" "," | sed "s/,$//g"` | ||||
|         if [ -n "$tmp" ]; then | ||||
|             echo "<vendor>$tmp</vendor>" >> "$ADAPTERFILE" | ||||
|         fi | ||||
|         tmp=`udevadm info /sys/class/net/"$nic" | grep ID_MODEL_FROM_DATABASE | awk -F '=' '{print $2}'` | ||||
|         if [ -n "$tmp" ]; then | ||||
|             echo "<model>$tmp</model>" >> "$ADAPTERFILE" | ||||
|         fi | ||||
|         echo '</nic>' >> "$ADAPTERFILE" | ||||
|     fi | ||||
| done | ||||
|  | ||||
| for pci in `lspci |awk '/Ethernet/ {print $1}' `; do | ||||
|     if ! grep -q "$pci" "$ADAPTERFILE" 2>/dev/null; then  | ||||
|         tmp=`lspci |grep "$pci"` | ||||
|         echo '<nic>' >> "$ADAPTERFILE" | ||||
|         echo "<pcilocation>$pci</pcilocation>" >> "$ADAPTERFILE" | ||||
|         echo "<model>${tmp##*:}</model>" >> "$ADAPTERFILE" | ||||
|         echo '</nic>' >> "$ADAPTERFILE" | ||||
|         fi | ||||
| done | ||||
|  | ||||
| for pci in `lspci |awk '/Network/ {print $1}' `; do | ||||
|     if ! grep -q "$pci" "$ADAPTERFILE" 2>/dev/null; then  | ||||
|         tmp=`lspci |grep "$pci"` | ||||
|         echo '<nic>' >> "$ADAPTERFILE" | ||||
|         echo "<pcilocation>$pci</pcilocation>" >> "$ADAPTERFILE" | ||||
|         echo "<model>${tmp##*: }</model>" >> "$ADAPTERFILE" | ||||
|         echo '</nic>' >> "$ADAPTERFILE" | ||||
|         fi | ||||
| done | ||||
|  | ||||
| for pci in `lspci |awk '/Mellanox/ {print $1}' `; do | ||||
|     if ! grep -q "$pci" "$ADAPTERFILE" 2>/dev/null; then  | ||||
|         tmp=`lspci |grep "$pci"` | ||||
|         echo '<nic>' >> "$ADAPTERFILE" | ||||
|         echo "<pcilocation>$pci</pcilocation>" >> "$ADAPTERFILE" | ||||
|         echo "<model>${tmp##*: }</model>" >> "$ADAPTERFILE" | ||||
|         echo '</nic>' >> "$ADAPTERFILE" | ||||
|         fi | ||||
| done | ||||
|  | ||||
| echo "</xcatrequest>" >> "$ADAPTERFILE" | ||||
|  | ||||
| #cat "$ADAPTERFILE" | ||||
|  | ||||
| if [ -n  "$XCATMASTER" ]; then | ||||
|     if [ -f /etc/xcat/cert.pem -a -f /etc/xcat/certkey.pem ]; then #use client cert if available | ||||
|         echo "using /etc/xcat/certkey.pem and /etc/xcat/cert.pem to transmit scan result to $XCATMASTER" >> "$SCANNICLOG" | ||||
|         openssl s_client -key /etc/xcat/certkey.pem -cert /etc/xcat/cert.pem -connect $XCATMASTER:$XCATPORT  <"$ADAPTERFILE" >>"$SCANNICLOG" 2>&1 | ||||
|     else | ||||
|         echo "transmit scan result without customer certificate to $XCATMASTER" >> "$SCANNICLOG" | ||||
|         openssl s_client -connect $XCATMASTER:$XCATPORT  <"$ADAPTERFILE"  >>"$SCANNICLOG" 2>&1 | ||||
|     fi | ||||
| else | ||||
|     dhcps=`awk -F ' |;' '/dhcp-server/ { print $(NF-1) }' /var/lib/dhclient/dhclient.leases | tail -n 1` | ||||
|     if [ -n "$dhcps" ]; then | ||||
|         if [ -f /etc/xcat/cert.pem -a -f /etc/xcat/certkey.pem ]; then #use client cert if available | ||||
|              echo "using /etc/xcat/certkey.pem and /etc/xcat/cert.pem to transmit scan result to $dhcps" >> "$SCANNICLOG" | ||||
|              openssl s_client -key /etc/xcat/certkey.pem -cert /etc/xcat/cert.pem -connect $dhcps:$XCATPORT  <"$ADAPTERFILE" >>"$SCANNICLOG" 2>&1 | ||||
|         else | ||||
|              echo "transmit scan result without customer certificate to $dhcps" >> "$SCANNICLOG" | ||||
|              openssl s_client -connect $dhcps:$XCATPORT  <"$ADAPTERFILE"  >>"$SCANNICLOG" 2>&1 | ||||
|         fi | ||||
|     fi | ||||
| fi | ||||
|  | ||||
							
								
								
									
										452
									
								
								xCAT-server/lib/xcat/plugins/getadapter.pm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										452
									
								
								xCAT-server/lib/xcat/plugins/getadapter.pm
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,452 @@ | ||||
| # IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html | ||||
| #------------------------------------------------------- | ||||
|  | ||||
| =head1 | ||||
|   xCAT plugin package to handle getadapters management | ||||
|  | ||||
|    Supported command: | ||||
|         getadapters->getadapters  | ||||
|         findadapter->getadapters  | ||||
|  | ||||
| =cut | ||||
|  | ||||
| #------------------------------------------------------- | ||||
| package xCAT_plugin::getadapter; | ||||
|  | ||||
| BEGIN{    | ||||
|    $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : -d '/opt/xcat' ? '/opt/xcat' : '/usr'; | ||||
| } | ||||
| use lib "$::XCATROOT/lib/perl"; | ||||
|  | ||||
| use xCAT::Table; | ||||
| use xCAT::Utils; | ||||
| use xCAT::MsgUtils; | ||||
| use Data::Dumper; | ||||
| use Getopt::Long; | ||||
| use File::Path; | ||||
| use IO::Select; | ||||
| use Term::ANSIColor; | ||||
| use Time::Local; | ||||
|  | ||||
| my %usage = ( | ||||
|     "getadapters" => "Usage:\n\tgetadapters [-h|--help|-v|--version|V]\n\tgetadapters <noderange> [-f]", | ||||
| ); | ||||
|  | ||||
| my $inforootdir = "/var/lib/xcat/adapters/"; | ||||
| my $VERBOSE=0; | ||||
| #------------------------------------------------------- | ||||
|  | ||||
| =head3  handled_commands | ||||
|  | ||||
| Return list of commands handled by this plugin | ||||
|  | ||||
| =cut | ||||
|  | ||||
| #------------------------------------------------------- | ||||
|  | ||||
| sub handled_commands | ||||
| { | ||||
|     return { | ||||
|         getadapters => "getadapter", | ||||
|         findadapter => "getadapter", | ||||
|     }; | ||||
| } | ||||
|  | ||||
| #------------------------------------------------------- | ||||
|  | ||||
| =head3  process_request | ||||
|  | ||||
|   Process the command | ||||
|  | ||||
| =cut | ||||
|  | ||||
| #------------------------------------------------------- | ||||
| sub process_request | ||||
| { | ||||
|     my $request  = shift; | ||||
|     my $callback = shift; | ||||
|     my $subreq   = shift; | ||||
|     my $command  = $request->{command}->[0]; | ||||
|  | ||||
|     $SIG{CHLD}='DEFAULT'; | ||||
|  | ||||
|     if ($command eq "getadapters"){ | ||||
|         &handle_getadapters($request, $callback, $subreq); | ||||
|     } | ||||
|  | ||||
|     if ($command eq "findadapter"){ | ||||
|         &handle_findadapter($request, $callback); | ||||
|     } | ||||
|  | ||||
|     return; | ||||
| } | ||||
|  | ||||
| sub handle_getadapters{ | ||||
|     my $request  = shift; | ||||
|     my $callback = shift; | ||||
|     my $subreq   = shift; | ||||
|     my $command  = $request->{command}->[0]; | ||||
|  | ||||
|     my @args=();  | ||||
|     my $HELP; | ||||
|     my $VERSION; | ||||
|     my $FORCE; | ||||
|     if (ref($request->{arg})) { | ||||
|         @args=@{$request->{arg}};    | ||||
|     } else {     | ||||
|         @args=($request->{arg}); | ||||
|     } | ||||
|     @ARGV = @args; | ||||
|     Getopt::Long::Configure("bundling");     | ||||
|     Getopt::Long::Configure("no_pass_through"); | ||||
|     if (!GetOptions("h|help"    => \$HELP,  | ||||
|            "v|version" => \$VERSION, | ||||
|            "f"         => \$FORCE, | ||||
|            "V"         => \$VERBOSE | ||||
|     ) ) { | ||||
|         if($usage{$command}) { | ||||
|             my $rsp = {}; | ||||
|             $rsp->{error}->[0] = $usage{$command}; | ||||
|             $rsp->{errorcode}->[0] = 1; | ||||
|             $callback->($rsp); | ||||
|         } | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     if ($HELP) { | ||||
|         if($usage{$command}) { | ||||
|             my %rsp; | ||||
|             $rsp{data}->[0]=$usage{$command}; | ||||
|             $callback->(\%rsp); | ||||
|         } | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     if ($VERSION) { | ||||
|         my $ver = xCAT::Utils->Version(); | ||||
|         my %rsp; | ||||
|         $rsp{data}->[0]="$ver"; | ||||
|         $callback->(\%rsp); | ||||
|         return;  | ||||
|     } | ||||
|  | ||||
|     my $tmpnodes = join(",", @{$request->{node}}); | ||||
|     my $tmpargs = join(",", @args); | ||||
|     xCAT::MsgUtils->trace($VERBOSE,"d","getadapters: handling command <$command $tmpnodes $tmpargs>"); | ||||
|  | ||||
|     if($FORCE || ! -d $inforootdir) { | ||||
|         my @tmpnodes = @{$request->{node}}; | ||||
|         $request->{missnode} = \@tmpnodes; | ||||
|         &scan_adapters($request, $callback, $subreq); | ||||
|     }else{ | ||||
|         my @nodes = @{$request->{node}}; | ||||
|         my $node; | ||||
|         my @missnodes = (); | ||||
|         foreach $node (@nodes){ | ||||
|             if ( ! -e "$inforootdir/$node.info" || -z "$inforootdir/$node.info"){ | ||||
|                 push @missnodes,$node; | ||||
|             }   | ||||
|         } | ||||
|  | ||||
|         if(scalar(@missnodes) != 0){ | ||||
|            $request->{missnode} = \@missnodes; | ||||
|            &scan_adapters($request, $callback, $subreq);  | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     &get_info_from_local($request, $callback);  | ||||
|     return; | ||||
|  | ||||
| } | ||||
|  | ||||
| sub handle_findadapter{ | ||||
|  | ||||
|     my $request  = shift; | ||||
|     my $callback = shift; | ||||
|     my $hostname = $request->{hostname}->[0]; | ||||
|  | ||||
|     xCAT::MsgUtils->trace($VERBOSE,"d","getadapters: receiving a findadapter response from $hostname"); | ||||
|  | ||||
|     my $nicnum = scalar @{$request->{nic}}; | ||||
|     my $content = ""; | ||||
|     #print "-----------nicnum = $nicnum----------------\n";  | ||||
|     for (my $i = 0; $i < $nicnum; $i++) { | ||||
|         $content .= "$i:"; | ||||
|         if(exists($request->{nic}->[$i]->{interface})){ | ||||
|             $content .= "hitname=".$request->{nic}->[$i]->{interface}->[0]."|"; | ||||
|         } | ||||
|         if(exists($request->{nic}->[$i]->{pcilocation})){ | ||||
|             $content .= "pci=".$request->{nic}->[$i]->{pcilocation}->[0]."|"; | ||||
|         } | ||||
|         if(exists($request->{nic}->[$i]->{mac})){ | ||||
|             $content .= "mac=".$request->{nic}->[$i]->{mac}->[0]."|"; | ||||
|         } | ||||
|         if(exists($request->{nic}->[$i]->{predictablename})){ | ||||
|             $content .= "candidatename=".$request->{nic}->[$i]->{predictablename}->[0]."|"; | ||||
|         } | ||||
|         if(exists($request->{nic}->[$i]->{vendor})){ | ||||
|             $content .= "vendor=".$request->{nic}->[$i]->{vendor}->[0]."|"; | ||||
|         } | ||||
|         if(exists($request->{nic}->[$i]->{model})){ | ||||
|             $content .= "model=".$request->{nic}->[$i]->{model}->[0]; | ||||
|         } | ||||
|         $content .= "\n"; | ||||
|     } | ||||
|     $content =~ s/\n$//; | ||||
|  | ||||
|     my $fd; | ||||
|     if(!open($fd,">$inforootdir/$hostname.info")) { | ||||
|         xCAT::MsgUtils->trace($VERBOSE,"d","findadapter: can't open $inforootdir/$hostname.info to record adapter info"); | ||||
|     }else{ | ||||
|         print $fd "$content"; | ||||
|         close($fd); | ||||
|     } | ||||
|  | ||||
|     return; | ||||
| } | ||||
|  | ||||
| sub scan_adapters{ | ||||
|     my $request  = shift; | ||||
|     my $callback = shift; | ||||
|     my $subreq   = shift; | ||||
|     my @targetscannodes = @{$request->{missnode}}; | ||||
|  | ||||
|     if (scalar(@{$request->{node}}) == 0){ | ||||
|         return 1; | ||||
|     } | ||||
|  | ||||
|     my $tmptargetnodes = join(",", @targetscannodes); | ||||
|     xCAT::MsgUtils->trace($VERBOSE,"d","getadapters: issue new scaning for $tmptargetnodes"); | ||||
|  | ||||
|     my %autorsp; | ||||
|     $autorsp{data}->[0]="-->Starting scan for: $tmptargetnodes"; | ||||
|     $callback->(\%autorsp); | ||||
|  | ||||
|     if ( ! -d $inforootdir){ | ||||
|         mkpath("$inforootdir"); | ||||
|     } | ||||
|  | ||||
|     my $node; | ||||
|     foreach $node (@targetscannodes){ | ||||
|         if ( -e "$inforootdir/$node.info"){ | ||||
|              rename("$inforootdir/$node.info", "$inforootdir/$node.info.bak");              | ||||
|              xCAT::MsgUtils->trace($VERBOSE,"d","getadapters: move $inforootdir/$node.info to $inforootdir/$node.info.bak"); | ||||
|         }else{ | ||||
|             open OUT,">$inforootdir/$node.first"  | ||||
|         }   | ||||
|     } | ||||
|  | ||||
|     #do scan stuff | ||||
|     my $pid; | ||||
|     my $forkcount = 0; | ||||
|     my %pidrecord; | ||||
|     foreach $node (@targetscannodes){ | ||||
|  | ||||
|         $pid = xCAT::Utils->xfork(); | ||||
|         if (!defined($pid)){   | ||||
|             $autorsp{info}->[0]="failed to fork process to restart $node"; | ||||
|             $callback->(\%autorsp); | ||||
|             deletenode($request->{missnode}, "$node"); | ||||
|             last; | ||||
|         }elsif ($pid == 0){ | ||||
|             # Child process | ||||
|             xCAT::MsgUtils->trace($VERBOSE,"d","getadapters: fork new process $$ to start scaning $node"); | ||||
|             | ||||
|             my $outref = xCAT::Utils->runxcmd( | ||||
|                 { | ||||
|                     command => ['nodeset'], | ||||
|                     node    => ["$node"], | ||||
|                     arg     => ['runcmd=getadapter'], | ||||
|                 }, | ||||
|                 ,$subreq, 0, 1); | ||||
|             if($::RUNCMD_RC != 0){ | ||||
|                 my $tmp = join(" ", @$outref); | ||||
|                 $autorsp{data}->[0]="$tmp"; | ||||
|                 $callback->(\%autorsp); | ||||
|                 exit(1); | ||||
|             } | ||||
|  | ||||
|             my $tab = xCAT::Table->new("nodehm"); | ||||
|             my $hmhash = $tab->getNodeAttribs(["$node"], ['mgt']); | ||||
|             $tab->close(); | ||||
|     | ||||
|             if ($hmhash->{mgt} eq "ipmi"){ | ||||
|                 $outref = xCAT::Utils->runxcmd( | ||||
|                     { | ||||
|                         command => ["rsetboot"], | ||||
|                         node    => ["$node"], | ||||
|                         arg     => ['net'], | ||||
|                     }, | ||||
|                     ,$subreq, 0, 1);  | ||||
|                 if($::RUNCMD_RC != 0){ | ||||
|                     my $tmp = join(" ", @$outref); | ||||
|                     $autorsp{data}->[0]="$tmp"; | ||||
|                     $callback->(\%autorsp); | ||||
|                     exit(1); | ||||
|                 }           | ||||
|  | ||||
|                 $outref = xCAT::Utils->runxcmd( | ||||
|                     { | ||||
|                         command => ['rpower'], | ||||
|                         node    => ["$node"], | ||||
|                         arg     => ['reset'], | ||||
|                     }, | ||||
|                     ,$subreq, 0, 1); | ||||
|                 if($::RUNCMD_RC != 0){ | ||||
|                     my $tmp = join(" ", @$outref); | ||||
|                     $autorsp{data}->[0]="$tmp"; | ||||
|                     $callback->(\%autorsp); | ||||
|                     exit(1); | ||||
|                 } | ||||
|             }else{ | ||||
|                 $outref = xCAT::Utils->runxcmd( | ||||
|                     { | ||||
|                         command => ["rnetboot"], | ||||
|                         node    => ["$node"], | ||||
|                     }, | ||||
|                     ,$subreq, 0, 1); | ||||
|                 if($::RUNCMD_RC != 0){ | ||||
|                     my $tmp = join(" ", @$outref); | ||||
|                     $autorsp{data}->[0]="$tmp"; | ||||
|                     $callback->(\%autorsp); | ||||
|                     exit(1); | ||||
|                 } | ||||
|             } | ||||
|             # Exit process | ||||
|             exit(0); | ||||
|         } | ||||
|         # Parent process | ||||
|         $forkcount++; | ||||
|         $pidrecord{$pid} = $node; | ||||
|     } | ||||
|  | ||||
|     # Wait for all processes to end | ||||
|     if($forkcount == 0){ | ||||
|         deletenode($request->{missnode}, "all"); | ||||
|         return 1;         | ||||
|     }else{ | ||||
|         while($forkcount){ | ||||
|             my $cpid; | ||||
|             while (($cpid=waitpid(-1,WNOHANG)) > 0) { | ||||
|                 my $cpr=$?; | ||||
|                 if($cpr>0){ | ||||
|                      deletenode($request->{missnode}, "$pidreord{$cpid}"); | ||||
|                 } | ||||
|                 $forkcount--; | ||||
|             } | ||||
|             sleep 0.1; | ||||
|         } | ||||
|     } | ||||
|     | ||||
|     check_scan_result($request, $callback); | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| sub check_scan_result{ | ||||
|     my $request = shift; | ||||
|     my $callback = shift; | ||||
|     my $retry =60; | ||||
|     my $rsp = {}; | ||||
|     my $nodenum = scalar @{$request->{missnode}}; | ||||
|     my $backnum = 0; | ||||
|   | ||||
|     if (exists($request->{missnode}) && (scalar(@{$request->{missnode}}) > 0)){ | ||||
|         while($retry && $backnum != $nodenum){ | ||||
|             sleep 10; | ||||
|             $retry--; | ||||
|             foreach $backnode (@{$request->{missnode}}){ | ||||
|                 if( -e "$inforootdir/$backnode.info" ){ | ||||
|                     $backnum++; | ||||
|                     deletenode($request->{missnode}, "$backnode"); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if($retry == 0 && $backnum != $nodenum){ | ||||
|         my $tmpnode = join(",", @{$request->{missnode}}); | ||||
|         push @{$rsp->{data}}, "waiting scan result for $tmpnode time out"; | ||||
|         $callback->($rsp); | ||||
|     }     | ||||
| } | ||||
|  | ||||
|  | ||||
| sub get_info_from_local{ | ||||
|     my $request  = shift; | ||||
|     my $callback = shift; | ||||
|     my $retry = 60; | ||||
|     my $rsp = {}; | ||||
|  | ||||
|     push @{$rsp->{data}}, "\nThe whole scan result:";       | ||||
|  | ||||
|     if (scalar(@{$request->{node}}) == 0){ | ||||
|         $callback->({ | ||||
|             error=>[qq{Please indicate the nodes which are needed to scan}],  | ||||
|             errorcode=>[1]}); | ||||
|         return 1; | ||||
|     } | ||||
|  | ||||
|     my $node; | ||||
|     foreach $node (@{$request->{node}}){ | ||||
|         my $readfile=1; | ||||
|         push @{$rsp->{data}}, "--------------------------------------"; | ||||
|         if ( ! -e "$inforootdir/$node.info" &&  ! -e "$inforootdir/$node.info.bak" ){ | ||||
|             push @{$rsp->{data}}, "[$node] Scan failed and without old data. there isn't data to show"; | ||||
|             $readfile=0; | ||||
|         }elsif( ! -e "$inforootdir/$node.info" && -e "$inforootdir/$node.info.bak" ){ | ||||
|             rename("$inforootdir/$node.info.bak","$inforootdir/$node.info"); | ||||
|             push @{$rsp->{data}}, "[$node] Scan failed but old data exist, using the old data:"; | ||||
|         }elsif( -e "$inforootdir/$node.info" && ! -e "$inforootdir/$node.info.bak" && ! -e "$inforootdir/$node.first"){ | ||||
|             push @{$rsp->{data}}, "[$node] with no need for scan due to old data exist, using the old data:"; | ||||
|         }elsif(-e "$inforootdir/$node.info" && ! -e "$inforootdir/$node.info.bak" && -e "$inforootdir/$node.first"){ | ||||
|             unlink "$inforootdir/$node.first"; | ||||
|             push @{$rsp->{data}}, "[$node] scan successfully, below are the latest data:"; | ||||
|         }else{ | ||||
|             unlink "$inforootdir/$node.info.bak"; | ||||
|             push @{$rsp->{data}}, "[$node] scan successfully, below are the latest data:"; | ||||
|         } | ||||
|         if($readfile){ | ||||
|             if( -z "$inforootdir/$node.info"){ | ||||
|                 push @{$rsp->{data}}, "[$node] the file is empty, nothing to show"; | ||||
|             }else{ | ||||
|                 if (open($myfile, "$inforootdir/$node.info")) { | ||||
|                     while ($line = <$myfile>) { | ||||
|                         push @{$rsp->{data}}, "$node:$line"; | ||||
|                     } | ||||
|                     close($myfile); | ||||
|                 }else{ | ||||
|                     push @{$rsp->{data}}, "[$node] Can't open $inforootdir/$node.info"; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     $callback->($rsp); | ||||
|  | ||||
|     return; | ||||
| } | ||||
|  | ||||
| sub deletenode{ | ||||
|     my $arrref = shift; | ||||
|     my $targetnode = shift; | ||||
|     my $arrcount = scalar @$arrref; | ||||
|     my $targetindex=0; | ||||
|  | ||||
|     if( "$targetnode" ne "all" ){ | ||||
|         for (my $i = 0; $i < $arrcount; $i++){ | ||||
|             if ("$arrref->[$i]" eq "$targetnode"){ | ||||
|                 $targetindex = $i; | ||||
|                 last; | ||||
|             } | ||||
|         } | ||||
|         for (my $i = $targetindex; $i < $arrcount-1; $i++){ | ||||
|             $arrref->[$i] = $arrref->[$i+1] ; | ||||
|         } | ||||
|         pop @$arrref; | ||||
|     }else{ | ||||
|         for (my $i = 0; $i < $arrcount; $i++){ | ||||
|             pop @$arrref; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| 1; | ||||
		Reference in New Issue
	
	Block a user