From e8df039d4204a4d7ad0702f351baebc64094105e Mon Sep 17 00:00:00 2001 From: chenglch Date: Wed, 19 Jul 2017 15:01:37 +0800 Subject: [PATCH] Make getadapter work during discovery process This patch redesign the original getadapter plugins. Currently, getadapter do not work as a common command but only a chain command works during discovery. --- docs/source/advanced/networks/getadapter.rst | 59 +- .../references/man1/getadapter.1.rst | 147 ---- xCAT-client/debian/xcat-client.links | 1 - xCAT-client/pods/man1/getadapter.1.pod | 94 --- xCAT-client/xCAT-client.spec | 1 - xCAT-genesis-scripts/bin/getadapter | 6 +- xCAT-server/lib/xcat/plugins/getadapter.pm | 663 ++---------------- xCAT-server/sbin/xcatconfig | 2 + 8 files changed, 81 insertions(+), 892 deletions(-) delete mode 100644 docs/source/guides/admin-guides/references/man1/getadapter.1.rst delete mode 100644 xCAT-client/pods/man1/getadapter.1.pod diff --git a/docs/source/advanced/networks/getadapter.rst b/docs/source/advanced/networks/getadapter.rst index c1ce39e48..43cdaa1a9 100644 --- a/docs/source/advanced/networks/getadapter.rst +++ b/docs/source/advanced/networks/getadapter.rst @@ -1,51 +1,42 @@ -Predict network adapter name before deployment +Predict network adapter name during discovery ============================================== +Traditionally, network interfaces in Linux are enumerated as eth[0123…], but +these names do not correspond to actual labels on the chassis. Now, most of +the linux distribution support naming the adapter with slot information which +makes adapter name predictable. xCAT add ``getadapter`` script which can be +running during discovery stage to detect the adapter names and pci slot +information to help customer configure the network. -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 ``getadapter`` 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 +How to use getadapter ----------------------- +Set the chian table to run ``getadapter`` script :: -Using below command to obtain the network adapters information :: - - getadapter + chdef chain="runcmd=getadapter" -Then will get output like below :: +When the discovery completed, the column ``nicsadapter`` of ```nics`` table is +updated. +View result with ``lsdef`` command :: - The whole scan result: - -------------------------------------- - [node2] scan successfully, below are the latest data - node2:[1]->eno1!mac=34:40:b5:be:6a:80|pci=/pci0000:00/0000:00:01.0/0000:0c:00.0|candidatename=eno1/enp12s0f0/enx3440b5be6a80 - node2:[2]->enp0s29u1u1u5!mac=36:40:b5:bf:44:33|pci=/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.1/2-1.1.5/2-1.1.5:1.0|candidatename=enp0s29u1u1u5/enx3640b5bf4433 - -------------------------------------- - [node1] scan successfully, below are the latest data - node1:[1]->eno1!mac=34:40:b5:be:6a:80|pci=/pci0000:00/0000:00:01.0/0000:0c:00.0|candidatename=eno1/enp12s0f0/enx3440b5be6a80 - node1:[2]->enp0s29u1u1u5!mac=36:40:b5:bf:44:33|pci=/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.1/2-1.1.5/2-1.1.5:1.0|candidatename=enp0s29u1u1u5/enx3640b5bf4433 + # lsdef + ....... + nicsadapter.enP3p3s0f0=mac=98:be:94:59:fa:cc linkstate=DOWN pci=/pci0003:00/0003:00:00.0/0003:01:00.0/0003:02:01.0/0003:03:00.0 candidatename=enP3p3s0f0/enx98be9459facc + nicsadapter.enP3p3s0f1=mac=98:be:94:59:fa:cd linkstate=DOWN pci=/pci0003:00/0003:00:00.0/0003:01:00.0/0003:02:01.0/0003:03:00.1 candidatename=enP3p3s0f1/enx98be9459facd + nicsadapter.enP3p3s0f2=mac=98:be:94:59:fa:ce linkstate=DOWN pci=/pci0003:00/0003:00:00.0/0003:01:00.0/0003:02:01.0/0003:03:00.2 candidatename=enP3p3s0f2/enx98be9459face + nicsadapter.enP3p3s0f3=mac=98:be:94:59:fa:cf linkstate=UP pci=/pci0003:00/0003:00:00.0/0003:01:00.0/0003:02:01.0/0003:03:00.3 candidatename=enP3p3s0f3/enx98be9459facf + ....... +Below are the information ``getadapter`` trying to inspect: -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. +* **name**: the real adapter name used by genesis operation system -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: - -* **name**: the consistent name which can be used by confignic directly in operating system which follow the same naming scheme with rhels7 - -* **pci**: the pci location +* **pci**: the pci slot 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) +* **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. (``confignetwork`` 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 - -* **linkstate**: The link state of network device +* **linkstate**: The link state of network device \ No newline at end of file diff --git a/docs/source/guides/admin-guides/references/man1/getadapter.1.rst b/docs/source/guides/admin-guides/references/man1/getadapter.1.rst deleted file mode 100644 index 316f4bcea..000000000 --- a/docs/source/guides/admin-guides/references/man1/getadapter.1.rst +++ /dev/null @@ -1,147 +0,0 @@ - -############ -getadapter.1 -############ - -.. highlight:: perl - - -**** -NAME -**** - - -\ **getadapter**\ - Obtain all network adapters's predictable name and some other information before provision or network configuration. - - -******** -SYNOPSIS -******** - - -\ **getadapter**\ \ *noderange*\ [\ **-f**\ ] - -\ **getadapter**\ [\ **-h | -**\ **-help | -v | -**\ **-version | -V**\ ] - - -*********** -DESCRIPTION -*********** - - -Traditionally, network interfaces in Linux are enumerated as eth[0123...], but these names do not necessarily correspond to actual labels on the chassis. \ **getadapter**\ help customer to get predictable network device name and some other network adapter information before provision or network configuration. - -\ **Since getadpter uses genesis to collect network adapters information, the target node will be restarted.**\ - -\ **getadapter**\ For each node within the , follows below scheme: - -If the target node is scanned for the first time, \ **getadapter**\ will trigger genesis to collect information then save the information at the \ **nicsadapter**\ column of nics table. -If the target node has ever been scanned, \ **getadapter**\ will use the information from nics table first. -If user hopes to scan the adapter information for the node but these information already exist, \ **-f**\ option can be used to start rescan process. - -\ **getadapter**\ tries to collect more information for the target network device, but doesn't guarantee collect same much information for every network device. - - -****************************** -\ **Collected information:**\ -****************************** - - - -\ **name**\ : the consistent name which can be used by confignic directly in operating system which follow the same naming scheme with rhels7 - - - -\ **pci**\ : the pci location - - - -\ **mac**\ : the MAC address - - - -\ **candidatename**\ : All the names which satisfy predictable network device naming scheme. \ *(if xcat enhance confignic command later, user can use these names to configure their network adapter, even customize their name)*\ - - - -\ **vender**\ : the vender of network device - - - -\ **model**\ : the model of network device - - - -\ **linkstate**\ : the link state of network device - - - - -******* -OPTIONS -******* - - -\ **-h**\ - -Display usage message. - -\ **-v**\ - -Command Version. - -\ **-V**\ - -Display verbose message. - -\ **-f**\ - -Force to trigger new round scan. ignore the data collected before. - - -******** -EXAMPLES -******** - - -1. To collect node[1-3]'s network device information, enter: - - -.. code-block:: perl - - getadapter node[1-2] - - -Output is similar to: - - -.. code-block:: perl - - -->Starting scan for: node1,node2 - The whole scan result: - -------------------------------------- - [node1]: Adapter information exists, no need to scan. - -------------------------------------- - [node2] scan successfully, below are the latest data - node2:[1]->eno1!mac=34:40:b5:be:6a:80|pci=/pci0000:00/0000:00:01.0/0000:0c:00.0|candidatename=eno1/enp12s0f0/enx3440b5be6a80 - node2:[2]->enp0s29u1u1u5!mac=36:40:b5:bf:44:33|pci=/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.1/2-1.1.5/2-1.1.5:1.0|candidatename=enp0s29u1u1u5/enx3640b5bf4433 - - -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 - - -.. code-block:: perl - - getadatper node -f - - - -******** -SEE ALSO -******** - - -noderange(3)|noderange.3 - diff --git a/xCAT-client/debian/xcat-client.links b/xCAT-client/debian/xcat-client.links index d1e323960..c9c0dc1b3 100644 --- a/xCAT-client/debian/xcat-client.links +++ b/xCAT-client/debian/xcat-client.links @@ -37,7 +37,6 @@ opt/xcat/bin/xcatclient opt/xcat/bin/lstree opt/xcat/bin/xcatclient opt/xcat/bin/lsflexnode opt/xcat/bin/xcatclient opt/xcat/bin/rmflexnode opt/xcat/bin/xcatclient opt/xcat/bin/mkflexnode -opt/xcat/bin/xcatclient opt/xcat/bin/getadapter opt/xcat/bin/xcatclientnnr opt/xcat/bin/lsslp opt/xcat/bin/xcatclient opt/xcat/bin/imgcapture opt/xcat/bin/xcatclientnnr opt/xcat/bin/swapnodes diff --git a/xCAT-client/pods/man1/getadapter.1.pod b/xCAT-client/pods/man1/getadapter.1.pod deleted file mode 100644 index 0bdb93c42..000000000 --- a/xCAT-client/pods/man1/getadapter.1.pod +++ /dev/null @@ -1,94 +0,0 @@ -=head1 NAME - -B - Obtain all network adapters's predictable name and some other information before provision or network configuration. - -=head1 SYNOPSIS - -B I [B<-f>] - -B [B<-h>|B<--help>|B<-v>|B<--version>|B<-V>] - -=head1 DESCRIPTION - -Traditionally, network interfaces in Linux are enumerated as eth[0123...], but these names do not necessarily correspond to actual labels on the chassis. B help customer to get predictable network device name and some other network adapter information before provision or network configuration. - -B - -B For each node within the , follows below scheme: - -If the target node is scanned for the first time, B will trigger genesis to collect information then save the information at the B column of nics table. -If the target node has ever been scanned, B will use the information from nics table first. -If user hopes to scan the adapter information for the node but these information already exist, B<-f> option can be used to start rescan process. - -B tries to collect more information for the target network device, but doesn't guarantee collect same much information for every network device. - -=head1 B - -=over 2 - -=item B: the consistent name which can be used by confignic directly in operating system which follow the same naming scheme with rhels7 - -=item B: the pci location - -=item B: the MAC address - -=item B: 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)> - -=item B: the vender of network device - -=item B: the model of network device - -=item B: the link state of network device - -=back - -=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: - - getadapter node[1-2] - -Output is similar to: - - -->Starting scan for: node1,node2 - The whole scan result: - -------------------------------------- - [node1]: Adapter information exists, no need to scan. - -------------------------------------- - [node2] scan successfully, below are the latest data - node2:[1]->eno1!mac=34:40:b5:be:6a:80|pci=/pci0000:00/0000:00:01.0/0000:0c:00.0|candidatename=eno1/enp12s0f0/enx3440b5be6a80 - node2:[2]->enp0s29u1u1u5!mac=36:40:b5:bf:44:33|pci=/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.1/2-1.1.5/2-1.1.5:1.0|candidatename=enp0s29u1u1u5/enx3640b5bf4433 - -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 - - getadatper node -f - - - -=head1 SEE ALSO - -L - - diff --git a/xCAT-client/xCAT-client.spec b/xCAT-client/xCAT-client.spec index 44235d213..d4d841dc6 100644 --- a/xCAT-client/xCAT-client.spec +++ b/xCAT-client/xCAT-client.spec @@ -163,7 +163,6 @@ ln -sf ../bin/xcatclient $RPM_BUILD_ROOT/%{prefix}/bin/lstree ln -sf ../bin/xcatclient $RPM_BUILD_ROOT/%{prefix}/bin/lsflexnode ln -sf ../bin/xcatclient $RPM_BUILD_ROOT/%{prefix}/bin/rmflexnode ln -sf ../bin/xcatclient $RPM_BUILD_ROOT/%{prefix}/bin/mkflexnode -ln -sf ../bin/xcatclient $RPM_BUILD_ROOT/%{prefix}/bin/getadapter ln -sf ../bin/xcatclientnnr $RPM_BUILD_ROOT/%{prefix}/bin/lsslp ln -sf ../bin/xcatclientnnr $RPM_BUILD_ROOT/%{prefix}/bin/switchdiscover ln -sf ../bin/xcatclientnnr $RPM_BUILD_ROOT/%{prefix}/bin/bmcdiscover diff --git a/xCAT-genesis-scripts/bin/getadapter b/xCAT-genesis-scripts/bin/getadapter index 25b11afaf..c91dae564 100755 --- a/xCAT-genesis-scripts/bin/getadapter +++ b/xCAT-genesis-scripts/bin/getadapter @@ -4,7 +4,6 @@ XCATPORT=3001 export XCATPORT -#XCATMASTER="10.3.5.21" ADAPTERFILE="/tmp/adapterinfo" SCANNICLOG="/tmp/adapterscan.log" @@ -17,8 +16,6 @@ fi echo " getadapter -cli -$HOSTNAME update" >> "$ADAPTERFILE" #scan adapters have recognized by operating system @@ -111,5 +108,4 @@ else openssl s_client -connect $dhcps:$XCATPORT <"$ADAPTERFILE" >>"$SCANNICLOG" 2>&1 fi fi -fi - +fi \ No newline at end of file diff --git a/xCAT-server/lib/xcat/plugins/getadapter.pm b/xCAT-server/lib/xcat/plugins/getadapter.pm index 3cdbe5bff..9fc989daa 100644 --- a/xCAT-server/lib/xcat/plugins/getadapter.pm +++ b/xCAT-server/lib/xcat/plugins/getadapter.pm @@ -2,7 +2,7 @@ #------------------------------------------------------- =head1 - xCAT plugin package to handle getadapter management + xCAT plugin package to handle getadapter request from genesis. Supported command: getadapter->getadapter @@ -18,37 +18,9 @@ BEGIN { use lib "$::XCATROOT/lib/perl"; use xCAT::Table; -use xCAT::Utils; -use xCAT::FifoPipe; -use xCAT::MsgUtils; use xCAT::State; use Data::Dumper; -use Getopt::Long; -use File::Path; -use Term::ANSIColor; -use Time::Local; use strict; -use Class::Struct; -use XML::Simple; -use Storable qw(dclone); - -my %usage = ( -"getadapter" => "Usage:\n\tgetadapter [-h|--help|-v|--version|V]\n\tgetadapter [-f]", -); - -my $VERBOSE = 0; -use constant OPT_FORCE => 0; -use constant OPT_UPDATE => 1; - -use constant GET_ADPATER_DIR => "/var/run/getadapter"; -use constant ALARM_TIMEOUT => 1800; - -unless (-d GET_ADPATER_DIR) { - mkpath(GET_ADPATER_DIR); -} - -my %child_pids; -my $timeout_event = 0; #------------------------------------------------------- @@ -67,50 +39,16 @@ sub handled_commands }; } -#------------------------------------------------------- - -=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{INT} = $SIG{TERM} = sub { - xCAT::MsgUtils->message("W", "getadapter: int or term signal received, clean up task state"); - exit(clean_up()); - }; - - if ($command eq "getadapter") { - &handle_getadapter($request, $callback, $subreq); - } - return; -} - #------------------------------------------------------------------ =head3 route_request - Route the request, this funciton is called in the reqeust process. + This subroutine is used for the command called from genesis. As the client of + genesis is not a command line interface, this hook comand can help save one + fork compare with a common command. - return REQUEST_UPDATE if update request arrived. Now just send - message to the waiting process with fifo pipe. - - (TODO) If getadapter is used in chain table to complete - the discovery process, the adapter information can be - updated directly in immediate plugin and there is no need - to fork plugin process. - - return REQUEST_WAIT if inspect request arrived. Tell xcatd fork - plugin process to handle this request. - return REQUEST_ERROR if error happened. + return REQUEST_UPDATE if request is received. + return REQUEST_ERROR if error happens. Usage example: This is a hook function in xcatd, do not use it directly. @@ -118,565 +56,70 @@ sub process_request #----------------------------------------------------------------- sub route_request { - my ($request, $callback, $subreq) = @_; + my $request = shift; my $command = $request->{command}->[0]; - my $ret = xCAT::State->REQUEST_ERROR; - - if (!$request->{node}) { - return xCAT::State->REQUEST_WAIT; + if ($command eq "getadapter") { + if (!defined($request->{'action'}) || $request->{action}->[0] ne xCAT::State->UPDATE_ACTION) { + return xCAT::State->REQUEST_ERROR; + } + my $node = $request->{'_xcat_clienthost'}->[0]; + if (!$request->{nic}) { + xCAT::MsgUtils->message("S", "$node: Could not get any nic information"); + return xCAT::State->REQUEST_ERROR; + } + my $nics = \@{ $request->{nic} }; + xCAT::MsgUtils->message("S", "$node: callback message from getadapter received"); + if (update_nics_info($node, $nics)!=0) { + return xCAT::State->REQUEST_ERROR; + } } - - my $build_request_message_func = sub { - my $req = shift; - my $xs = new XML::Simple(); - my $nic_info; - $nic_info->{'nic'} = $req->{'nic'}; - $nic_info->{'node'} = $req->{node}->[0]; - return $xs->XMLout($nic_info); - }; - - if (defined($request->{'action'}) and $request->{action}->[0] eq xCAT::State->UPDATE_ACTION) { - - # may be a callback request, just check the state then send message - # no need to fork a plugin process. - my $node = ${ $request->{'node'} }[0]; - my $taskstate_table = xCAT::Table->new('taskstate'); - unless ($taskstate_table) { - xCAT::MsgUtils->message("S", "Unable to open taskstate table, denying"); - return $ret; - } - my $node_obj = $taskstate_table->getAttribs({ 'node' => $node, 'command' => $command }, 'state', 'pid'); - - if (defined($node_obj) and $node_obj->{'state'} eq xCAT::State->WAIT_STATE) { - my $msg_queue = xCAT::FifoPipe->send_message( - xCAT::Utils->full_path($node_obj->{'pid'}, GET_ADPATER_DIR), - &$build_request_message_func($request)); - $ret = xCAT::State->REQUEST_UPDATE; - } - else { - xCAT::MsgUtils->message("S", "Error to find the node in waiting state"); - } - $taskstate_table->close(); - } elsif (!defined($request->{'action'}) or $request->{action}->[0] eq xCAT::State->INSPECT_ACTION) { - - # new request, fork a plugin child process to handle this request. - $ret = xCAT::State->REQUEST_WAIT; - } - return $ret; + return xCAT::State->REQUEST_UPDATE; } -#------------------------------------------------------- - -=head3 handle_getadapter - - This function check the command option, then call the - function to complete the request. - - Usage example: - This function is called from process_request, - do not call it directly. -=cut - -#------------------------------------------------------- - -sub handle_getadapter { - my $request = shift; - my $callback = shift; - my $subreq = shift; - my $command = $request->{command}->[0]; - my @opts; - - my @args = (); - my $HELP; - my $VERSION; - my $FORCE; - my $UPDATE; - 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, - "u" => \$UPDATE, - "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; - } - @opts = ($FORCE, $UPDATE); - - if (!defined($request->{'action'}) or $request->{action}->[0] eq xCAT::State->INSPECT_ACTION) { - return inspect_adapter($request, $callback, $subreq, \@opts); - } - - return; -} - -#------------------------------------------------------------------ - -=head3 clean_up - - Clean up the getadapter running environment - - return 1 if clean up failed - - Usage example: - clean_up() -=cut - -#----------------------------------------------------------------- -sub clean_up { - my $ret = 0; - foreach (keys %child_pids) { - kill 2, $_; - } - xCAT::MsgUtils->message("S", "Getadapter: clean up task state in database"); - - # NOTE(chenglch): Currently xcatd listener process has bug in signal handler, - # just comment out these code. - my $taskstate_table = xCAT::Table->new('taskstate'); - - if ($taskstate_table) { - $taskstate_table->delEntries({ 'pid' => getppid() }); - $taskstate_table->close(); - } - else { - xCAT::MsgUtils->message("S", "Clean up taskstate error"); - $ret = 1; - } - xCAT::FifoPipe->remove_pipe(xCAT::Utils->full_path(getppid(), GET_ADPATER_DIR)); - return $ret; -} - - -#------------------------------------------------------------------ - -=head3 deploy_genesis - - Fork processes to boot the target node into genesis - - return array of nodes which are booting geneses. - - Usage example: - my @nodes= ('node1', 'node2', 'node3'); - my $nodes_desc_ptr, a hash pointer to the description of nodes array. - @nodes = deploy_genesis(\@nodes, $nodes_desc_ptr, $callback, $subreq); - -=cut - -#----------------------------------------------------------------- -sub deploy_genesis { - my $nodes_ptr = shift; - my $nodes_desc_ptr = shift; - my $callback = shift; - my $subreq = shift; - my @nodes = @{$nodes_ptr}; - my $pid; - - my $child_process_func = sub { - my ($node, $node_desc_ptr, $callback, $subreq) = @_; - my $outref = xCAT::Utils->runxcmd( - { - command => ['rinstall'], - node => ["$node"], - arg => ['runcmd=getadapter'], - }, - $subreq, 0, 1); - if ($::RUNCMD_RC != 0) { - foreach my $out (@$outref) { - $callback->({data => "$out"}) - } - $callback->({ error => "failed to run command: rinstall $node runcmd=getadapter", errorcode => 1 }); - return 1; - } - $callback->({ data => "$node: Booting into genesis, this could take several minutes..." }); - return 0; - }; # end of child_process_func - - $SIG{CHLD} = 'DEFAULT'; - foreach my $node (@nodes) { - $pid = xCAT::Utils->xfork(); - if (!defined($pid)) { - $callback->({ error => "failed to fork process to restart $node", errorcode => 1 }); - $node = undef; - last; - } elsif ($pid == 0) { - - # child process - $SIG{INT} = $SIG{TERM} = 'DEFAULT'; - my $node_desc_ptr = $nodes_desc_ptr->{$node}; - xCAT::MsgUtils->trace($VERBOSE, "d", "getadapter: fork new process $$ to start scaning $node"); - my $ret = &$child_process_func($node, $node_desc_ptr, $callback, $subreq); - exit($ret); - } else { - - # Parent process - $child_pids{$pid} = $node; - } - } - - # Wait for all processes to end - my $cpid = 0; - while (keys %child_pids) { - if (($cpid = wait()) > 0) { - my $status = $?; - if ($status != 0) { - my $node = $child_pids{$cpid}; - - #delete nodes if child process error. - map { $_ = undef if $_ eq $node } @nodes; - } - delete $child_pids{$cpid}; - } - } - - # delete undef - @nodes = grep /./, @nodes; - return @nodes; -} - -#------------------------------------------------------------------ - -=head3 update_adapter_result - - Update the adapter information in the nics table. - Print the adapter information to STDOUT. - - Input: - $msg: A hash pointer parsed from message from fifopipe - $nodes_desc_ptr: Nodes description pointer - $opts_ptr: A pointer to the nodes option - $callback: callback object - - return -1 if unexpectd error. - return 0 success - - Usage example: - my $msg; - my $nodes_desc_ptr; - my $opts_ptr; - my $callback - update_adapter_result($msg, $nodes_desc_ptr, $opts_ptr, $callback)); - -=cut - -#----------------------------------------------------------------- -sub update_adapter_result { - my $msg = shift; - my $nodes_desc_ptr = shift; - my $opts_ptr = shift; - my $callback = shift; - my $node = $msg->{'node'}; - my $nicnum = scalar @{ $msg->{nic} }; - my ($output, $data, $interface_exists, $has_nic, %updates); - - $data = ""; - $output = "[$node] scan successfully below is result:\n"; - for (my $i = 0 ; $i < $nicnum ; $i++) { - $output .= "$node:[$i]->"; - $interface_exists = 0; - - if (exists($msg->{nic}->[$i]->{interface})) { - $output .= $msg->{nic}->[$i]->{interface}."!"; - if ($has_nic) { - $data .= "," . $msg->{nic}->[$i]->{interface} . "!"; - } - else { - $data .= $msg->{nic}->[$i]->{interface} . "!"; - } - $interface_exists = 1; - $has_nic = 1; - } - my @nic_attrs = (); - my @output_attrs = (); - if (exists($msg->{nic}->[$i]->{mac})) { - push(@output_attrs, "mac=" . $msg->{nic}->[$i]->{mac}); - if ($interface_exists) { - push(@nic_attrs, "mac=" . $msg->{nic}->[$i]->{mac}); - } - } - if (exists($msg->{nic}->[$i]->{pcilocation})) { - push(@output_attrs, "pci=" . $msg->{nic}->[$i]->{pcilocation}); - if ($interface_exists) { - push(@nic_attrs, "pci=" . $msg->{nic}->[$i]->{pcilocation}); - } - } - if (exists($msg->{nic}->[$i]->{predictablename})) { - push(@output_attrs, "candidatename=" . $msg->{nic}->[$i]->{predictablename}); - } - if (exists($msg->{nic}->[$i]->{vendor})) { - $msg->{nic}->[$i]->{vendor} =~ s/^\s+|\s+$//g; - push(@output_attrs, "vendor=" . $msg->{nic}->[$i]->{vendor}); - } - if (exists($msg->{nic}->[$i]->{model})) { - $msg->{nic}->[$i]->{model} =~ s/^\s+|\s+$//g; - push(@output_attrs, "model=" . $msg->{nic}->[$i]->{model}); - } - if (exists($msg->{nic}->[$i]->{linkstate})) { - push(@output_attrs, "linkstate=" . (split(' ', $msg->{nic}->[$i]->{linkstate}))[0]); - if ($interface_exists) { - push(@nic_attrs, "linkstate=". (split(' ', $msg->{nic}->[$i]->{linkstate}))[0]); - } - } - if (@nic_attrs) { - $data .= join(" ", @nic_attrs); - } - $output .= join("|", @output_attrs); - $output .= "\n"; - } - $callback->({ data => "$output" }); - if (!$has_nic) { - $callback->({ data => "$node: nics table will not be updated as not any ". - "useful information could be found with udevadm command." }); - return 0; - } - my $nics_table = xCAT::Table->new('nics'); - unless ($nics_table) { - xCAT::MsgUtils->message("S", "Unable to open nics table, denying"); - $callback->({ error => "Error to connect to nics table.", - errorcode => 1 }); - return -1; - } - $updates{'nicsadapter'} = $data; - if ($nics_table->setAttribs({ 'node' => $node }, \%updates) != 0) { - xCAT::MsgUtils->message("S", "Error to update nics table."); - $callback->({ error => "Error to update nics table.", - errorcode => 1 }); - return -1; - } - return 0; -} - -#------------------------------------------------------------------ - -=head3 do_inspect - - The main function to run the getadapter process - - - Input: - $nodesptr: The nodes pointer - $nodes_desc_ptr: Nodes description pointer - $opts_ptr: Option pointer - $callback: callback object - $subreq: xcat sub request - - return -1 if unexpectd error. - return 0 success - -=cut - -#----------------------------------------------------------------- - -sub do_inspect { - my $nodesptr = shift; - my $nodes_desc_ptr = shift; - my $opts_ptr = shift; - my $callback = shift; - my $subreq = shift; - my @nodes = @{$nodesptr}; - my $updates; - my $msg; # parse from xml - - my $parse_request_message_func = sub { - my $xml = shift; - my $xs = new XML::Simple(); - return $xs->XMLin($xml); - }; - - my $timeout_output_func = sub { - my $nodes_ptr = shift; - my $callback = shift; - foreach my $node (@{$nodes_ptr}) { - if ($node) { - $callback->({ error => "$node: Timeout to get the adapter information", - errorcode => 1 }); - } - } - }; - - my $taskstate_table = xCAT::Table->new('taskstate'); - unless ($taskstate_table) { - xCAT::MsgUtils->message("S", "Unable to open taskstate table, denying"); - $callback->({ error => "Error to connect to taskstate table.", - errorcode => 1 }); - return -1; - } - - # TODO(chenglch) Currently xcat db access is a single process model, this is - # safe. In the future: - # 1. If database is refactored, we need to protect the task - # state with Optimistic Lock of database. - # 2. If we leverage the memcache or other cache database, we can make use of - # the feature of the CAS to provide the atomic operation. - foreach my $node (@nodes) { - $updates->{$node}->{'command'} = "getadapter"; - $updates->{$node}->{'state'} = xCAT::State->WAIT_STATE; - $updates->{$node}->{'pid'} = getppid(); - } - $taskstate_table->setNodesAttribs($updates); - $taskstate_table->close(); - @nodes = deploy_genesis(\@nodes, $nodes_desc_ptr, $callback, $subreq); - my $total = scalar(@nodes); - my $count = 0; - my @node_buf; - - $SIG{ALRM} = sub { - xCAT::MsgUtils->message("W", "getadapter: alarm signal received"); - $timeout_event = 1; - - # pipe broken, wake up the wait fifo pipe - xCAT::FifoPipe->remove_pipe(xCAT::Utils->full_path(getppid(), GET_ADPATER_DIR)); - }; - alarm(ALARM_TIMEOUT); - - while ($count < $total) { - my $c = xCAT::FifoPipe->recv_message( - xCAT::Utils->full_path(getppid(), GET_ADPATER_DIR), - \@node_buf); - if ($c <= 0) { - if ($timeout_event == 1) { - &$timeout_output_func(\@nodes, $callback); - clean_up(); - return -1; - } - xCAT::MsgUtils->message("S", "Unexpected pipe error, abort."); - return -1; - } +sub update_nics_info { + my $node = shift; + my $nics_ptr = shift; + my (@nics, @data, %updates); + @nics = @{$nics_ptr}; + my $update_nics_table_func = sub { + my $node = shift; + my $nics = shift; my $nics_table = xCAT::Table->new('nics'); unless ($nics_table) { - xCAT::MsgUtils->message("S", "Unable to open nics table, denying"); + xCAT::MsgUtils->message("S", "Unable to open nics table for getadapter, denying"); return -1; } - - my $taskstate_table = xCAT::Table->new('taskstate'); - unless ($taskstate_table) { - xCAT::MsgUtils->message("S", "Unable to open taskstate table, denying"); + $updates{'nicsadapter'} = $nics; + if ($nics_table->setAttribs({ 'node' => $node }, \%updates) != 0) { + xCAT::MsgUtils->message("S", "Error to update nics table for getadapter."); return -1; } - - for (my $i = 0 ; $i < $c ; $i++) { - $msg = &$parse_request_message_func($node_buf[$i]); - - # delete the node - map { $_ = undef if $_ eq $msg->{'node'} } @nodes; - if (update_adapter_result($msg, $nodes_desc_ptr, $opts_ptr, $callback)) { - return -1; - } - $taskstate_table->delEntries({ 'node' => $msg->{'node'} }); - } - $count += $c; - $taskstate_table->close(); $nics_table->close(); - } - xCAT::MsgUtils->trace($VERBOSE, "d", "getadapter: remove pipe " . xCAT::Utils->full_path(getppid(), GET_ADPATER_DIR)); - xCAT::FifoPipe->remove_pipe(xCAT::Utils->full_path(getppid(), GET_ADPATER_DIR)); - return 0; -} - -#------------------------------------------------------------------ - -=head3 inspect_adapter - - Process the getadapter command option. - - return -1 if unexpectd error. - return 0 success. - -=cut - -#----------------------------------------------------------------- -sub inspect_adapter { - my $request = shift; - my $callback = shift; - my $subreq = shift; - my $opts_ptr = shift; - my @nodes; - my @entries; - my %nodes_desc; - - my $init_desc_func = sub { - my $nodes_ptr = shift; - my $callback = shift; - my $nodes_desc_ptr = shift; - my @nodes = @{$nodes_ptr}; - my $nodehm_table = xCAT::Table->new('nodehm'); - unless ($nodehm_table) { - xCAT::MsgUtils->message("S", "Unable to open nodehm table, denying"); - return -1; - } - my $entries = $nodehm_table->getNodesAttribs($nodes_ptr, ['mgt']); - unless ($entries) { - xCAT::MsgUtils->message("S", "No records about " . join(",", @nodes) . " in nodehm table"); - return -1; - } - $nodehm_table->close(); - foreach my $node (@nodes) { - if (!defined($entries->{$node}) || !defined($entries->{$node}->[0]->{mgt})) { - $callback->({ error => "$node: mgt configuration can not be found.", - errorcode => 1 }); - next; - } - $nodes_desc_ptr->{$node}->{'mgt'} = $entries->{$node}->[0]->{mgt}; - } return 0; - }; # end of init_desc_func + }; - # Get the nodes should be inspect. - if ($opts_ptr->[OPT_FORCE]) { - @nodes = @{ $request->{node} }; - } else { - my $nics_table = xCAT::Table->new('nics'); - unless ($nics_table) { - xCAT::MsgUtils->message("S", "Unable to open nics table, denying"); - return -1; - } - my $entries = $nics_table->getNodesAttribs($request->{node}, ['nicsadapter']); - foreach my $node (@{ $request->{node} }) { - if ($entries->{$node} && $entries->{$node}->[0]->{nicsadapter}) { - $callback->({ data => "$node: Adapter information exists, no need to inspect." }); - next; + for (my $i = 0; $i < scalar(@nics); $i++) { + if ($nics[$i]->{interface}) { + my @nic_attrs = (); + if ($nics[$i]->{mac}) { + push(@nic_attrs, "mac=".$nics[$i]->{mac}->[0]); + } + if ($nics[$i]->{linkstate}) { + push (@nic_attrs, "linkstate=". (split(' ', $nics[$i]->{linkstate}->[0]))[0]); + } + if($nics[$i]->{pcilocation}) { + push(@nic_attrs, "pci=" . $nics[$i]->{pcilocation}->[0]); + } + if ($nics[$i]->{predictablename}) { + push(@nic_attrs, "candidatename=" . $nics[$i]->{predictablename}->[0]); + } + if (@nic_attrs) { + push(@data, $nics[$i]->{interface}->[0]."!".join(" ", @nic_attrs)); } - push(@nodes, $node); } } - if (scalar(@nodes) == 0) { - $callback->({ data => "No adapter information need to inspect." }); - return -1; - } - xCAT::MsgUtils->trace($VERBOSE, "d", "getadapter: scaning start for " . join(",", @nodes)); - if (&$init_desc_func(\@nodes, $callback, \%nodes_desc)) { - return -1; - } - return do_inspect(\@nodes, \%nodes_desc, $opts_ptr, $callback, $subreq); + return $update_nics_table_func->($node, join(",", @data)); } 1; diff --git a/xCAT-server/sbin/xcatconfig b/xCAT-server/sbin/xcatconfig index 51a3f1469..be5e512ca 100755 --- a/xCAT-server/sbin/xcatconfig +++ b/xCAT-server/sbin/xcatconfig @@ -1383,6 +1383,8 @@ sub initDB "$::XCATROOT/sbin/chtab priority=2.3 policy.commands=lsxcatd policy.rule=allow;"; $chtabcmds .= "$::XCATROOT/sbin/chtab priority=2.1 policy.commands=remoteimmsetup policy.rule=allow;"; + $chtabcmds .= +"$::XCATROOT/sbin/chtab priority=4.9 policy.commands=getadapter policy.rule=allow;"; my $outref = xCAT::Utils->runcmd("$chtabcmds", 0); if ($::RUNCMD_RC != 0)