From e8df039d4204a4d7ad0702f351baebc64094105e Mon Sep 17 00:00:00 2001 From: chenglch Date: Wed, 19 Jul 2017 15:01:37 +0800 Subject: [PATCH 1/2] 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) From bc6ddccbd06e3600d438c58bc45f2629d8920aed Mon Sep 17 00:00:00 2001 From: chenglch Date: Fri, 21 Jul 2017 16:19:24 +0800 Subject: [PATCH 2/2] Modify the document and nics schema based on review comments. --- docs/source/advanced/networks/getadapter.rst | 4 ++-- perl-xCAT/xCAT/Schema.pm | 2 +- xCAT-server/lib/xcat/plugins/getadapter.pm | 1 - 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/docs/source/advanced/networks/getadapter.rst b/docs/source/advanced/networks/getadapter.rst index 43cdaa1a9..38188f486 100644 --- a/docs/source/advanced/networks/getadapter.rst +++ b/docs/source/advanced/networks/getadapter.rst @@ -5,7 +5,7 @@ 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 +run during discovery stage to detect the adapter names and pci slot information to help customer configure the network. @@ -16,7 +16,7 @@ Set the chian table to run ``getadapter`` script :: chdef chain="runcmd=getadapter" -When the discovery completed, the column ``nicsadapter`` of ```nics`` table is +After the discovery completed, the column ``nicsadapter`` of ```nics`` table is updated. View result with ``lsdef`` command :: diff --git a/perl-xCAT/xCAT/Schema.pm b/perl-xCAT/xCAT/Schema.pm index a19207611..832c8566d 100755 --- a/perl-xCAT/xCAT/Schema.pm +++ b/perl-xCAT/xCAT/Schema.pm @@ -1566,7 +1566,7 @@ passed as argument rather than by table value', The xCAT object definition commands support to use nicextraparams. as the sub attributes.', nicdevices => 'Comma-separated list of NIC device per NIC, multiple ethernet devices can be bonded as bond device, these ethernet devices are separated by | . !|,!, e.g. bond0!eth0|eth2,br0!bond0. The xCAT object definition commands support to use nicdevices. as the sub attributes.', nicsadapter => 'Comma-separated list of extra parameters that will be used for each NIC configuration. - !|,!|, for example, eth0!MTU=1500|MTU=1460,ib0!MTU=65520 CONNECTED_MODE=yes.', + !,!, for example, enP3p3s0f1!mac=98:be:94:59:fa:cd linkstate=DOWN,enP3p3s0f2!mac=98:be:94:59:fa:ce candidatename=enP3p3s0f2/enx98be9459face', comments => 'Any user-written notes.', disable => "Set to 'yes' or '1' to comment out this row.", }, diff --git a/xCAT-server/lib/xcat/plugins/getadapter.pm b/xCAT-server/lib/xcat/plugins/getadapter.pm index 9fc989daa..5cf212a2f 100644 --- a/xCAT-server/lib/xcat/plugins/getadapter.pm +++ b/xCAT-server/lib/xcat/plugins/getadapter.pm @@ -19,7 +19,6 @@ use lib "$::XCATROOT/lib/perl"; use xCAT::Table; use xCAT::State; -use Data::Dumper; use strict; #-------------------------------------------------------