mirror of
https://github.com/xcat2/xcat-core.git
synced 2025-06-17 20:00:19 +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