From 47b92c193f28fe3cffb6ab13c25640d77684f40f Mon Sep 17 00:00:00 2001 From: Bin Xu Date: Fri, 14 Jul 2017 13:50:58 +0800 Subject: [PATCH 1/7] Fix #3088, introduce 'disjointnetboot' site attribute to make nodeset request will only be handled for managed nodes on SN. --- .../admin-guides/references/man5/site.5.rst | 4 ++ perl-xCAT/xCAT/Schema.pm | 3 + xCAT-server/lib/xcat/plugins/grub2.pm | 62 ++++++++++++++----- xCAT-server/lib/xcat/plugins/petitboot.pm | 60 +++++++++++++----- xCAT-server/lib/xcat/plugins/xnba.pm | 57 ++++++++++++----- 5 files changed, 140 insertions(+), 46 deletions(-) diff --git a/docs/source/guides/admin-guides/references/man5/site.5.rst b/docs/source/guides/admin-guides/references/man5/site.5.rst index 9e48d38c2..39a8fdc5b 100644 --- a/docs/source/guides/admin-guides/references/man5/site.5.rst +++ b/docs/source/guides/admin-guides/references/man5/site.5.rst @@ -298,6 +298,10 @@ site Attributes: If value is set to a hostname, the directory in tftpdir will be mounted from that hostname on the SN + disjointnetboot: Only avaialbe when sharedtftp is set to 0/no. If set to '1', a service node + handles the netboot (petitboot/grub2/xnba) config file only for the nodes it manages. + The default value is '0'. '0' means handle all the nodes in the same subnet. + sharedinstall: Indicates if a shared file system will be used for installation resources. Possible values are: 'no', 'sns', or 'all'. 'no' means a shared file system is not being used. 'sns' means a diff --git a/perl-xCAT/xCAT/Schema.pm b/perl-xCAT/xCAT/Schema.pm index a19207611..b5badda23 100755 --- a/perl-xCAT/xCAT/Schema.pm +++ b/perl-xCAT/xCAT/Schema.pm @@ -1171,6 +1171,9 @@ passed as argument rather than by table value', " in tftpdir is mounted on all on Service Nodes. Default is 1/yes.\n" . " If value is set to a hostname, the directory in tftpdir\n" . " will be mounted from that hostname on the SN\n\n" . +" disjointnetboot: Only available when sharedtftp is set to 0/no. If set to '1', a service node\n" . +" handles the netboot (petitboot/grub2/xnba) config file only for the nodes it manages.\n" . +" The default value is '0'. '0' means handle all the nodes in the same subnet.\n\n" . " sharedinstall: Indicates if a shared file system will be used for installation\n" . " resources. Possible values are: 'no', 'sns', or 'all'. 'no' \n" . " means a shared file system is not being used. 'sns' means a\n" . diff --git a/xCAT-server/lib/xcat/plugins/grub2.pm b/xCAT-server/lib/xcat/plugins/grub2.pm index f6600d22c..5d4fa8dd8 100644 --- a/xCAT-server/lib/xcat/plugins/grub2.pm +++ b/xCAT-server/lib/xcat/plugins/grub2.pm @@ -1,6 +1,6 @@ # IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html package xCAT_plugin::grub2; -use Data::Dumper; +#use Data::Dumper; use Sys::Syslog; use xCAT::Scope; use xCAT::Utils; @@ -123,12 +123,10 @@ sub setstate { # We are in the service node pools, print error if no facing ip. if (xCAT::InstUtils->is_me($sn)) { - my @myself = xCAT::NetworkUtils->determinehostname(); - my $myname = $myself[ (scalar @myself) - 1 ]; $::callback->( { error => [ - "$myname: $ipfnd[1] on service node $sn" + "$::myxcatname: $ipfnd[1] on service node $sn" ], errorcode => [1] } @@ -140,7 +138,7 @@ sub setstate { $::callback->( { error => [ - "$myname: $ipfnd[1]" + "$::myxcatname: $ipfnd[1]" ], errorcode => [1] } @@ -486,6 +484,7 @@ sub preprocess_request { return xCAT::Scope->get_broadcast_scope_with_parallel($req); } } + # Do not dispatch to service nodes if non-sharedtftp or the node range contains only SNs. return xCAT::Scope->get_parallel_scope($req); } @@ -528,27 +527,56 @@ sub process_request { return; } - #if not shared tftpdir, then filter, otherwise, set up everything + my @hostinfo = xCAT::NetworkUtils->determinehostname(); + $::myxcatname = $hostinfo[(scalar @hostinfo) - 1]; + xCAT::MsgUtils->trace(0, "d", "grub2: running on $::myxcatname"); + + my @unmanagednodes = (); + #if not shared tftpdir, then broadcast, otherwise, set up everything if ($request->{'_disparatetftp'}->[0]) { #reading hint from preprocess_command @nodes = (); - my @hostinfo = xCAT::NetworkUtils->determinehostname(); - my $cur_xmaster = pop @hostinfo; - xCAT::MsgUtils->trace(0, "d", "grub2: running on $cur_xmaster"); - # Get current server managed node list + my %iphash = (); + # flag the IPs or names in iphash + foreach (@hostinfo) { $iphash{$_} = 1; } + #print Dumper(\%iphash); + + my $mynodeonly = 0; + my @entries = xCAT::TableUtils->get_site_attribute("disjointnetboot"); + my $t_entry = $entries[0]; + if (defined($t_entry)) { + $mynodeonly = $t_entry; + } + xCAT::MsgUtils->trace($verbose_on_off, "d", "grub2: disjointnetboot=$mynodeonly"); + + # Get managed node list under current server + # The node will be under under 'site.master' if no 'noderes.servicenode' is defined my $sn_hash = xCAT::ServiceNodeUtils->getSNformattedhash(\@rnodes, "xcat", "MN"); - my %managed = {}; - foreach (@{ $sn_hash->{$cur_xmaster} }) { $managed{$_} = 1; } + #print Dumper($sn_hash); + my %managed = (); + foreach (keys %$sn_hash) { + if (exists($iphash{$_})) { + my $cur_xmaster = $_; + foreach (@{ $sn_hash->{$cur_xmaster} }) { $managed{$_} = 1; } + last; + } + } foreach (@rnodes) { + # For MN, the scope is all CN, for SN, the scope is the nodes it managed if disjointnetboot is set. + my $req2manage = exists($managed{$_}) || xCAT::Utils->isMN(); + if ($mynodeonly == 1 && $req2manage != 1) { + push @unmanagednodes, $_; + next; + } + # Only handle its boot configuration files if the node in same subnet if (xCAT::NetworkUtils->nodeonmynet($_)) { push @nodes, $_; } else { my $msg = "grub2 configuration file was not created for node [$_] because sharedtftp attribute is not set and the node is not on same network as this xcatmaster"; - if ( $cur_xmaster ) { - $msg .= ": $cur_xmaster"; - } - if ( exists( $managed{$_} ) ) { + $msg .= ": $::myxcatname" if ( $::myxcatname ); + + if ($req2manage == 1) { # report error when it is under my control but I cannot handle it. my $rsp; $rsp->{data}->[0] = $msg; @@ -619,7 +647,7 @@ sub process_request { bootparams => \%bphash }, \&pass_along); if ($errored) { - xCAT::MsgUtils->trace($verbose_on_off, "d", "petitboot: Failed in processing setdestiny. Processing will not continue."); + xCAT::MsgUtils->trace($verbose_on_off, "d", "grub2: Failed in processing setdestiny. Processing will not continue."); return; } } diff --git a/xCAT-server/lib/xcat/plugins/petitboot.pm b/xCAT-server/lib/xcat/plugins/petitboot.pm index 04f7bcdf7..1b2248423 100644 --- a/xCAT-server/lib/xcat/plugins/petitboot.pm +++ b/xCAT-server/lib/xcat/plugins/petitboot.pm @@ -1,6 +1,7 @@ # IBM(c) 2014 EPL license http://www.eclipse.org/legal/epl-v10.html package xCAT_plugin::petitboot; +#use Data::Dumper; use File::Path; use Getopt::Long; use xCAT::Table; @@ -125,12 +126,10 @@ sub setstate { # We are in the service node pools, print error if no facing ip. if (xCAT::InstUtils->is_me($sn)) { - my @myself = xCAT::NetworkUtils->determinehostname(); - my $myname = $myself[ (scalar @myself) - 1 ]; $::callback->( { error => [ - "$myname: $ipfnd[1] on service node $sn" + "$::myxcatname: $ipfnd[1] on service node $sn" ], errorcode => [1] } @@ -142,7 +141,7 @@ sub setstate { $::callback->( { error => [ - "$myname: $ipfnd[1]" + "$::myxcatname: $ipfnd[1]" ], errorcode => [1] } @@ -363,6 +362,7 @@ sub preprocess_request { return xCAT::Scope->get_broadcast_scope_with_parallel($req); } } + # Do not dispatch to service nodes if non-sharedtftp or the node range contains only SNs. return xCAT::Scope->get_parallel_scope($req); } @@ -408,27 +408,57 @@ sub process_request { return; } - #if not shared tftpdir, then filter, otherwise, set up everything + my @hostinfo = xCAT::NetworkUtils->determinehostname(); + $::myxcatname = $hostinfo[(scalar @hostinfo) - 1]; + xCAT::MsgUtils->trace(0, "d", "petitboot: running on $::myxcatname"); + + my @unmanagednodes = (); + #if not shared tftpdir, then broadcast, otherwise, set up everything if ($request->{'_disparatetftp'}->[0]) { #reading hint from preprocess_command @nodes = (); - my @hostinfo = xCAT::NetworkUtils->determinehostname(); - my $cur_xmaster = pop @hostinfo; - xCAT::MsgUtils->trace(0, "d", "petitboot: running on $cur_xmaster"); - # Get current server managed node list + my %iphash = (); + # flag the IPs or names in iphash + foreach (@hostinfo) { $iphash{$_} = 1; } + #print Dumper(\%iphash); + + my $mynodeonly = 0; + my @entries = xCAT::TableUtils->get_site_attribute("disjointnetboot"); + my $t_entry = $entries[0]; + if (defined($t_entry)) { + $mynodeonly = $t_entry; + } + xCAT::MsgUtils->trace($verbose_on_off, "d", "petitboot: disjointnetboot=$mynodeonly"); + + # Get managed node list under current server + # The node will be under under 'site.master' if no 'noderes.servicenode' is defined my $sn_hash = xCAT::ServiceNodeUtils->getSNformattedhash(\@rnodes, "xcat", "MN"); - my %managed = {}; - foreach (@{ $sn_hash->{$cur_xmaster} }) { $managed{$_} = 1; } + #print Dumper($sn_hash); + my %managed = (); + foreach (keys %$sn_hash) { + if (exists($iphash{$_})) { + my $cur_xmaster = $_; + foreach (@{ $sn_hash->{$cur_xmaster} }) { $managed{$_} = 1; } + last; + } + } foreach (@rnodes) { + # For MN, the scope is all CN, for SN, the scope is the nodes it managed if disjointnetboot is set. + my $req2manage = exists($managed{$_}) || xCAT::Utils->isMN(); + if ($mynodeonly == 1 && $req2manage != 1) { + push @unmanagednodes, $_; + next; + } + + # Only handle its boot configuration files if the node in same subnet if (xCAT::NetworkUtils->nodeonmynet($_)) { push @nodes, $_; } else { my $msg = "petitboot configuration file was not created for node [$_] because sharedtftp attribute is not set and the node is not on same network as this xcatmaster"; - if ( $cur_xmaster ) { - $msg .= ": $cur_xmaster"; - } - if ( exists( $managed{$_} ) ) { + $msg .= ": $::myxcatname" if ( $::myxcatname ); + + if ($req2manage == 1) { # report error when it is under my control but I cannot handle it. my $rsp; $rsp->{data}->[0] = $msg; diff --git a/xCAT-server/lib/xcat/plugins/xnba.pm b/xCAT-server/lib/xcat/plugins/xnba.pm index dd8fe9d1c..773b75065 100644 --- a/xCAT-server/lib/xcat/plugins/xnba.pm +++ b/xCAT-server/lib/xcat/plugins/xnba.pm @@ -411,6 +411,7 @@ sub preprocess_request { return xCAT::Scope->get_broadcast_scope_with_parallel($req); } } + # Do not dispatch to service nodes if non-sharedtftp or the node range contains only SNs. return xCAT::Scope->get_parallel_scope($req); } @@ -450,28 +451,56 @@ sub process_request { return; } - #if not shared, then help sync up + my @hostinfo = xCAT::NetworkUtils->determinehostname(); + $::myxcatname = $hostinfo[(scalar @hostinfo) - 1]; + xCAT::MsgUtils->trace(0, "d", "xnba: running on $::myxcatname"); + + my @unmanagednodes = (); + #if not shared tftpdir, then broadcast, otherwise, set up everything if ($::XNBA_request->{'_disparatetftp'}->[0]) { #reading hint from preprocess_command @nodes = (); - my @hostinfo = xCAT::NetworkUtils->determinehostname(); - my $cur_xmaster = pop @hostinfo; - xCAT::MsgUtils->trace(0, "d", "xnba: running on $cur_xmaster"); - - # Get current server managed node list - my $sn_hash = xCAT::ServiceNodeUtils->getSNformattedhash(\@rnodes, "xcat", "MN"); - my %managed = {}; - foreach (@{ $sn_hash->{$cur_xmaster} }) { $managed{$_} = 1; } - # Whatever the node managed by this xcatmaster explicitly, if the node in same subnet, we need to handle its boot configuration files + my %iphash = (); + # flag the IPs or names in iphash + foreach (@hostinfo) { $iphash{$_} = 1; } + #print Dumper(\%iphash); + + my $mynodeonly = 0; + my @entries = xCAT::TableUtils->get_site_attribute("disjointnetboot"); + my $t_entry = $entries[0]; + if (defined($t_entry)) { + $mynodeonly = $t_entry; + } + xCAT::MsgUtils->trace($verbose_on_off, "d", "xnba: disjointnetboot=$mynodeonly"); + + # Get managed node list under current server + # The node will be under under 'site.master' if no 'noderes.servicenode' is defined + my $sn_hash = xCAT::ServiceNodeUtils->getSNformattedhash(\@rnodes, "xcat", "MN"); + #print Dumper($sn_hash); + my %managed = (); + foreach (keys %$sn_hash) { + if (exists($iphash{$_})) { + my $cur_xmaster = $_; + foreach (@{ $sn_hash->{$cur_xmaster} }) { $managed{$_} = 1; } + last; + } + } + foreach (@rnodes) { + # For MN, the scope is all CN, for SN, the scope is the nodes it managed if disjointnetboot is set. + my $req2manage = exists($managed{$_}) || xCAT::Utils->isMN(); + if ($mynodeonly == 1 && $req2manage != 1) { + push @unmanagednodes, $_; + next; + } + # Only handle its boot configuration files if the node in same subnet if (xCAT::NetworkUtils->nodeonmynet($_)) { push @nodes, $_; } else { my $msg = "xnba configuration file was not created for node [$_] because sharedtftp attribute is not set and the node is not on same network as this xcatmaster"; - if ( $cur_xmaster ) { - $msg .= ": $cur_xmaster"; - } - if ( exists( $managed{$_} ) ) { + $msg .= ": $::myxcatname" if ( $::myxcatname ); + + if ($req2manage == 1) { # report error when it is under my control but I cannot handle it. my $rsp; $rsp->{data}->[0] = $msg; From 9b2f597ec2d6118174707344f899a84817803c6c Mon Sep 17 00:00:00 2001 From: Bin Xu Date: Mon, 17 Jul 2017 14:44:34 +0800 Subject: [PATCH 2/7] Polish the code according to the review comments --- xCAT-server/lib/xcat/plugins/grub2.pm | 49 +++++++++++++++-------- xCAT-server/lib/xcat/plugins/petitboot.pm | 48 ++++++++++++++-------- xCAT-server/lib/xcat/plugins/xnba.pm | 48 ++++++++++++++-------- 3 files changed, 97 insertions(+), 48 deletions(-) diff --git a/xCAT-server/lib/xcat/plugins/grub2.pm b/xCAT-server/lib/xcat/plugins/grub2.pm index 5d4fa8dd8..f2a0b0958 100644 --- a/xCAT-server/lib/xcat/plugins/grub2.pm +++ b/xCAT-server/lib/xcat/plugins/grub2.pm @@ -528,7 +528,7 @@ sub process_request { } my @hostinfo = xCAT::NetworkUtils->determinehostname(); - $::myxcatname = $hostinfo[(scalar @hostinfo) - 1]; + $::myxcatname = $hostinfo[-1]; xCAT::MsgUtils->trace(0, "d", "grub2: running on $::myxcatname"); my @unmanagednodes = (); @@ -562,28 +562,45 @@ sub process_request { } } + my $notsamenet_nodes_err = ''; + my $notsamenet_nodes_warn = ''; + foreach (@rnodes) { # For MN, the scope is all CN, for SN, the scope is the nodes it managed if disjointnetboot is set. - my $req2manage = exists($managed{$_}) || xCAT::Utils->isMN(); - if ($mynodeonly == 1 && $req2manage != 1) { + my $req2manage = exists($managed{$_}); + if ($req2manage) { push @unmanagednodes, $_; - next; + # quick pass through if disjoint is set. + next if ( $mynodeonly == 1 && xCAT::Utils->isMN() != 1 ); } + # Only handle its boot configuration files if the node in same subnet if (xCAT::NetworkUtils->nodeonmynet($_)) { push @nodes, $_; - } else { - my $msg = "grub2 configuration file was not created for node [$_] because sharedtftp attribute is not set and the node is not on same network as this xcatmaster"; - $msg .= ": $::myxcatname" if ( $::myxcatname ); + } elsif ( $req2manage ) { + # report error when it is under my control but I cannot handle it. + $notsamenet_nodes_err .= " $_"; + } + else { + $notsamenet_nodes_warn .= " $_"; + } + } - if ($req2manage == 1) { - # report error when it is under my control but I cannot handle it. - my $rsp; - $rsp->{data}->[0] = $msg; - xCAT::MsgUtils->message("E", $rsp, $callback); - } else { - xCAT::MsgUtils->message("S", $msg); - } + if ( $mynodeonly == 1 && scalar (@unmanagednodes) > 0 && xCAT::Utils->isMN() != 1) { + my $str_umnodes = join(" ", @unmanagednodes); + xCAT::MsgUtils->trace($verbose_on_off, "d", "grub2: unmanaged nodes are $str_umnodes"); + } + + if ( $notsamenet_nodes_err || $notsamenet_nodes_warn ) { + my $msg = "grub2 configuration file was not created "; + $msg .= "on $::myxcatname " if ( $::myxcatname ); + $msg .= "for below nodes because sharedtftp attribute is not set and the nodes are not on same network as this xcatmaster: "; + xCAT::MsgUtils->message("S", $msg . $notsamenet_nodes_warn . $notsamenet_nodes_err); + # For managed children, need to report error + if ( $notsamenet_nodes_err ) { + my $rsp; + $rsp->{data}->[0] = $msg . $notsamenet_nodes_err; + xCAT::MsgUtils->message("E", $rsp, $callback); } } } else { @@ -592,7 +609,7 @@ sub process_request { #>>>>>>>used for trace log>>>>>>> my $str_node = join(" ", @nodes); - xCAT::MsgUtils->trace($verbose_on_off, "d", "grub2: nodes are $str_node"); + xCAT::MsgUtils->trace($verbose_on_off, "d", "grub2: nodes are $str_node") if ($str_node); # return directly if no nodes in the same network unless (@nodes) { diff --git a/xCAT-server/lib/xcat/plugins/petitboot.pm b/xCAT-server/lib/xcat/plugins/petitboot.pm index 1b2248423..23493336f 100644 --- a/xCAT-server/lib/xcat/plugins/petitboot.pm +++ b/xCAT-server/lib/xcat/plugins/petitboot.pm @@ -409,7 +409,7 @@ sub process_request { } my @hostinfo = xCAT::NetworkUtils->determinehostname(); - $::myxcatname = $hostinfo[(scalar @hostinfo) - 1]; + $::myxcatname = $hostinfo[-1]; xCAT::MsgUtils->trace(0, "d", "petitboot: running on $::myxcatname"); my @unmanagednodes = (); @@ -443,29 +443,45 @@ sub process_request { } } + my $notsamenet_nodes_err = ''; + my $notsamenet_nodes_warn = ''; + foreach (@rnodes) { # For MN, the scope is all CN, for SN, the scope is the nodes it managed if disjointnetboot is set. - my $req2manage = exists($managed{$_}) || xCAT::Utils->isMN(); - if ($mynodeonly == 1 && $req2manage != 1) { + my $req2manage = exists($managed{$_}); + if ($req2manage) { push @unmanagednodes, $_; - next; + # quick pass through if disjoint is set. + next if ( $mynodeonly == 1 && xCAT::Utils->isMN() != 1 ); } # Only handle its boot configuration files if the node in same subnet if (xCAT::NetworkUtils->nodeonmynet($_)) { push @nodes, $_; - } else { - my $msg = "petitboot configuration file was not created for node [$_] because sharedtftp attribute is not set and the node is not on same network as this xcatmaster"; - $msg .= ": $::myxcatname" if ( $::myxcatname ); + } elsif ( $req2manage ) { + # report error when it is under my control but I cannot handle it. + $notsamenet_nodes_err .= " $_"; + } + else { + $notsamenet_nodes_warn .= " $_"; + } + } - if ($req2manage == 1) { - # report error when it is under my control but I cannot handle it. - my $rsp; - $rsp->{data}->[0] = $msg; - xCAT::MsgUtils->message("E", $rsp, $callback); - } else { - xCAT::MsgUtils->message("S", $msg); - } + if ( $mynodeonly == 1 && scalar (@unmanagednodes) > 0 && xCAT::Utils->isMN() != 1) { + my $str_umnodes = join(" ", @unmanagednodes); + xCAT::MsgUtils->trace($verbose_on_off, "d", "petitboot: unmanaged nodes are $str_umnodes"); + } + + if ( $notsamenet_nodes_err || $notsamenet_nodes_warn ) { + my $msg = "petitboot configuration file was not created "; + $msg .= "on $::myxcatname " if ( $::myxcatname ); + $msg .= "for below nodes because sharedtftp attribute is not set and the nodes are not on same network as this xcatmaster: "; + xCAT::MsgUtils->message("S", $msg . $notsamenet_nodes_warn . $notsamenet_nodes_err); + # For managed children, need to report error + if ( $notsamenet_nodes_err ) { + my $rsp; + $rsp->{data}->[0] = $msg . $notsamenet_nodes_err; + xCAT::MsgUtils->message("E", $rsp, $callback); } } } else { @@ -474,7 +490,7 @@ sub process_request { #>>>>>>>used for trace log>>>>>>> my $str_node = join(" ", @nodes); - xCAT::MsgUtils->trace($verbose_on_off, "d", "petitboot: nodes are $str_node"); + xCAT::MsgUtils->trace($verbose_on_off, "d", "petitboot: nodes are $str_node") if ($str_node); # return directly if no nodes in the same network unless (@nodes) { diff --git a/xCAT-server/lib/xcat/plugins/xnba.pm b/xCAT-server/lib/xcat/plugins/xnba.pm index 773b75065..52b459ce2 100644 --- a/xCAT-server/lib/xcat/plugins/xnba.pm +++ b/xCAT-server/lib/xcat/plugins/xnba.pm @@ -452,7 +452,7 @@ sub process_request { } my @hostinfo = xCAT::NetworkUtils->determinehostname(); - $::myxcatname = $hostinfo[(scalar @hostinfo) - 1]; + $::myxcatname = $hostinfo[-1]; xCAT::MsgUtils->trace(0, "d", "xnba: running on $::myxcatname"); my @unmanagednodes = (); @@ -486,29 +486,45 @@ sub process_request { } } + my $notsamenet_nodes_err = ''; + my $notsamenet_nodes_warn = ''; + foreach (@rnodes) { # For MN, the scope is all CN, for SN, the scope is the nodes it managed if disjointnetboot is set. - my $req2manage = exists($managed{$_}) || xCAT::Utils->isMN(); - if ($mynodeonly == 1 && $req2manage != 1) { + my $req2manage = exists($managed{$_}); + if ($req2manage) { push @unmanagednodes, $_; - next; + # quick pass through if disjoint is set. + next if ( $mynodeonly == 1 && xCAT::Utils->isMN() != 1 ); } + # Only handle its boot configuration files if the node in same subnet if (xCAT::NetworkUtils->nodeonmynet($_)) { push @nodes, $_; - } else { - my $msg = "xnba configuration file was not created for node [$_] because sharedtftp attribute is not set and the node is not on same network as this xcatmaster"; - $msg .= ": $::myxcatname" if ( $::myxcatname ); + } elsif ( $req2manage ) { + # report error when it is under my control but I cannot handle it. + $notsamenet_nodes_err .= " $_"; + } + else { + $notsamenet_nodes_warn .= " $_"; + } + } - if ($req2manage == 1) { - # report error when it is under my control but I cannot handle it. - my $rsp; - $rsp->{data}->[0] = $msg; - xCAT::MsgUtils->message("E", $rsp, $::XNBA_callback); - } else { - xCAT::MsgUtils->message("S", $msg); - } + if ( $mynodeonly == 1 && scalar (@unmanagednodes) > 0 && xCAT::Utils->isMN() != 1) { + my $str_umnodes = join(" ", @unmanagednodes); + xCAT::MsgUtils->trace($verbose_on_off, "d", "xnba: unmanaged nodes are $str_umnodes"); + } + if ( $notsamenet_nodes_err || $notsamenet_nodes_warn ) { + my $msg = "xnba configuration file was not created "; + $msg .= "on $::myxcatname " if ( $::myxcatname ); + $msg .= "for below nodes because sharedtftp attribute is not set and the nodes are not on same network as this xcatmaster: "; + xCAT::MsgUtils->message("S", $msg . $notsamenet_nodes_warn . $notsamenet_nodes_err); + # For managed children, need to report error + if ( $notsamenet_nodes_err ) { + my $rsp; + $rsp->{data}->[0] = $msg . $notsamenet_nodes_err; + xCAT::MsgUtils->message("E", $rsp, $::XNBA_callback); } } } else { @@ -517,7 +533,7 @@ sub process_request { #>>>>>>>used for trace log>>>>>>> my $str_node = join(" ", @nodes); - xCAT::MsgUtils->trace(0, "d", "xnba: nodes are $str_node"); + xCAT::MsgUtils->trace(0, "d", "xnba: nodes are $str_node") if ($str_node); # return directly if no nodes in the same network unless (@nodes) { From 9dd5c3e986e41f1b5afa05dd2a80e399c4fc8e4b Mon Sep 17 00:00:00 2001 From: Bin Xu Date: Mon, 17 Jul 2017 19:49:39 +0800 Subject: [PATCH 3/7] Fix typo --- xCAT-server/lib/xcat/plugins/grub2.pm | 4 ++-- xCAT-server/lib/xcat/plugins/petitboot.pm | 4 ++-- xCAT-server/lib/xcat/plugins/xnba.pm | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/xCAT-server/lib/xcat/plugins/grub2.pm b/xCAT-server/lib/xcat/plugins/grub2.pm index f2a0b0958..cbe35783f 100644 --- a/xCAT-server/lib/xcat/plugins/grub2.pm +++ b/xCAT-server/lib/xcat/plugins/grub2.pm @@ -626,8 +626,8 @@ sub process_request { #now run the begin part of the prescripts unless ($args[0] eq 'stat') { # or $args[0] eq 'enact') { $errored = 0; - if ($request->{'_disparatetftp'}->[0]) { #the call is distrubuted to the service node already, so only need to handles my own children - xCAT::MsgUtils->trace($verbose_on_off, "d", "grub2: the call is distrubuted to the service node already, so only need to handles my own children"); + if ($request->{'_disparatetftp'}->[0]) { #the call is distrubuted to the service node already, so only need to handle my own children + xCAT::MsgUtils->trace($verbose_on_off, "d", "grub2: the call is distrubuted to the service node already, so only need to handle my own children"); xCAT::MsgUtils->trace($verbose_on_off, "d", "grub2: issue runbeginpre request"); $sub_req->({ command => ['runbeginpre'], node => \@nodes, diff --git a/xCAT-server/lib/xcat/plugins/petitboot.pm b/xCAT-server/lib/xcat/plugins/petitboot.pm index 23493336f..7b9487da3 100644 --- a/xCAT-server/lib/xcat/plugins/petitboot.pm +++ b/xCAT-server/lib/xcat/plugins/petitboot.pm @@ -507,8 +507,8 @@ sub process_request { #now run the begin part of the prescripts unless ($args[0] eq 'stat') { # or $args[0] eq 'enact') { $errored = 0; - if ($request->{'_disparatetftp'}->[0]) { #the call is distrubuted to the service node already, so only need to handles my own children - xCAT::MsgUtils->trace($verbose_on_off, "d", "petitboot: the call is distrubuted to the service node already, so only need to handles my own children"); + if ($request->{'_disparatetftp'}->[0]) { #the call is distrubuted to the service node already, so only need to handle my own children + xCAT::MsgUtils->trace($verbose_on_off, "d", "petitboot: the call is distrubuted to the service node already, so only need to handle my own children"); xCAT::MsgUtils->trace($verbose_on_off, "d", "petitboot: issue runbeginpre request"); $sub_req->({ command => ['runbeginpre'], node => \@nodes, diff --git a/xCAT-server/lib/xcat/plugins/xnba.pm b/xCAT-server/lib/xcat/plugins/xnba.pm index 52b459ce2..6464a70c3 100644 --- a/xCAT-server/lib/xcat/plugins/xnba.pm +++ b/xCAT-server/lib/xcat/plugins/xnba.pm @@ -700,7 +700,7 @@ sub process_request { #now run the end part of the prescripts unless ($args[0] eq 'stat') { # or $args[0] eq 'enact') $errored = 0; - if ($::XNBA_request->{'_disparatetftp'}->[0]) { #the call is distrubuted to the service node already, so only need to handles my own children + if ($::XNBA_request->{'_disparatetftp'}->[0]) { #the call is distrubuted to the service node already, so only need to handle my own children xCAT::MsgUtils->trace($verbose_on_off, "d", "xnba: issue runendpre request"); $sub_req->({ command => ['runendpre'], node => \@nodes, From 53d3b1bcedb077242ff4f2fb3a6c21ec5c5e2076 Mon Sep 17 00:00:00 2001 From: Bin Xu Date: Mon, 24 Jul 2017 13:32:40 +0800 Subject: [PATCH 4/7] 1, use 'disjointdhcps' for nodeset disjoint mode 2, handle 'disjoint' in preprocess method, to make sure that no request will be sent to SN which does not manage the nodes. 3, refine 'stat' to make sure it could query unmanaged nodes on-demand. --- .../admin-guides/references/man5/site.5.rst | 9 +- .../references/man8/nodeset.8.rst | 4 +- perl-xCAT/xCAT/NetworkUtils.pm | 55 +++- perl-xCAT/xCAT/Schema.pm | 8 +- perl-xCAT/xCAT/Scope.pm | 69 +++- perl-xCAT/xCAT/Usage.pm | 2 +- xCAT-client/pods/man8/nodeset.8.pod | 4 +- xCAT-server/lib/xcat/plugins/grub2.pm | 252 +++++++------- xCAT-server/lib/xcat/plugins/petitboot.pm | 310 ++++++++++-------- xCAT-server/lib/xcat/plugins/xnba.pm | 250 +++++++------- 10 files changed, 574 insertions(+), 389 deletions(-) diff --git a/docs/source/guides/admin-guides/references/man5/site.5.rst b/docs/source/guides/admin-guides/references/man5/site.5.rst index 39a8fdc5b..7fb2bf6cc 100644 --- a/docs/source/guides/admin-guides/references/man5/site.5.rst +++ b/docs/source/guides/admin-guides/references/man5/site.5.rst @@ -110,8 +110,9 @@ site Attributes: dhcplease: The lease time for the dhcp client. The default value is 43200. disjointdhcps: If set to '1', the .leases file on a service node only contains - the nodes it manages. The default value is '0'. - '0' value means include all the nodes in the subnet. + the nodes it manages. And when 'sharedtftp' is disabled, nodeset handles + boot loader configuration on a service node only for the nodes it manages. + The default value is '0'. It means include all the nodes in the subnet. pruneservices: Whether to enable service pruning when noderm is run (i.e. removing DHCP entries when noderm is executed) @@ -298,10 +299,6 @@ site Attributes: If value is set to a hostname, the directory in tftpdir will be mounted from that hostname on the SN - disjointnetboot: Only avaialbe when sharedtftp is set to 0/no. If set to '1', a service node - handles the netboot (petitboot/grub2/xnba) config file only for the nodes it manages. - The default value is '0'. '0' means handle all the nodes in the same subnet. - sharedinstall: Indicates if a shared file system will be used for installation resources. Possible values are: 'no', 'sns', or 'all'. 'no' means a shared file system is not being used. 'sns' means a diff --git a/docs/source/guides/admin-guides/references/man8/nodeset.8.rst b/docs/source/guides/admin-guides/references/man8/nodeset.8.rst index 35edfcd45..50d12e87c 100644 --- a/docs/source/guides/admin-guides/references/man8/nodeset.8.rst +++ b/docs/source/guides/admin-guides/references/man8/nodeset.8.rst @@ -19,7 +19,7 @@ Name **************** -\ **nodeset**\ \ *noderange*\ [\ **boot**\ | \ **stat**\ | \ **offline**\ | \ **runcmd=bmcsetup**\ | \ **osimage**\ [=\ *imagename*\ ] | \ **shell**\ | \ **shutdown**\ ] +\ **nodeset**\ \ *noderange*\ [\ **boot**\ | \ **stat**\ [\ **-a**\ ]| \ **offline**\ | \ **runcmd=bmcsetup**\ | \ **osimage**\ [=\ *imagename*\ ] | \ **shell**\ | \ **shutdown**\ ] \ **nodeset**\ \ *noderange*\ \ **osimage**\ [=\ *imagename*\ ] [\ **-**\ **-noupdateinitrd**\ ] [\ **-**\ **-ignorekernelchk**\ ] @@ -101,7 +101,7 @@ A user can supply their own scripts to be run on the mn or on the service node ( \ **stat**\ - Display the current boot loader config file description for the nodes requested + Display the current boot loader config file description for the nodes requested. When \ **disjointdhcps**\ is set, using \ **-a**\ to display them on all available service nodes. diff --git a/perl-xCAT/xCAT/NetworkUtils.pm b/perl-xCAT/xCAT/NetworkUtils.pm index d54bf253b..9b65054a2 100755 --- a/perl-xCAT/xCAT/NetworkUtils.pm +++ b/perl-xCAT/xCAT/NetworkUtils.pm @@ -1645,10 +1645,14 @@ sub getNodeIPaddress { require xCAT::Table; my $nodetocheck = shift; - my $port = shift; - my $nodeip; + if ($nodetocheck eq 'xCAT::NetworkUtils') { #was called with -> syntax + $nodetocheck = shift; + } - $nodeip = xCAT::NetworkUtils->getipaddr($nodetocheck); + # Quick return if pass in an IP + return $nodetocheck if (xCAT::NetworkUtils->isIpaddr($nodetocheck)); + + my $nodeip = xCAT::NetworkUtils->getipaddr($nodetocheck); if (!$nodeip) { my $hoststab = xCAT::Table->new('hosts'); @@ -1666,6 +1670,51 @@ sub getNodeIPaddress } +#------------------------------------------------------------------------------- + +=head3 checkNodeIPaddress + Arguments: + Node name only one at a time + Returns: a hash object contains IP or Error + Globals: + none + Example: my $ipresult = xCAT::NetworkUtils::checkNodeIPaddress($nodetocheck); + +=cut + +#------------------------------------------------------------------------------- + +sub checkNodeIPaddress +{ + require xCAT::Table; + my $nodetocheck = shift; + if ($nodetocheck eq 'xCAT::NetworkUtils') { #was called with -> syntax + $nodetocheck = shift; + } + my $ret; + + my $nodeip; + my $hoststab = xCAT::Table->new('hosts'); + my $ent = $hoststab->getNodeAttribs($nodetocheck, ['ip']); + if ($ent->{'ip'}) { + $nodeip = $ent->{'ip'}; + } + + # Get the IP from DNS + my $dnsip = xCAT::NetworkUtils->getipaddr($nodetocheck); + if (!$dnsip) + { + $ret->{'error'} = "The $nodetocheck can not be resolved."; + $ret->{'ip'} = $nodeip if ($nodeip); + } elsif (!$nodeip) { + $ret->{'ip'} = $dnsip; + } else { + $ret->{'ip'} = $nodeip; + $ret->{'error'} = "Defined IP address of $nodetocheck is inconsistent with DNS." if ($nodeip ne $dnsip); + } + return $ret; +} + #------------------------------------------------------------------------------- diff --git a/perl-xCAT/xCAT/Schema.pm b/perl-xCAT/xCAT/Schema.pm index b5badda23..67a220457 100755 --- a/perl-xCAT/xCAT/Schema.pm +++ b/perl-xCAT/xCAT/Schema.pm @@ -1029,8 +1029,9 @@ passed as argument rather than by table value', " dhcpsetup: If set to 'n', it will skip the dhcp setup process in the nodeset cmd.\n\n" . " dhcplease: The lease time for the dhcp client. The default value is 43200.\n\n" . " disjointdhcps: If set to '1', the .leases file on a service node only contains\n" . -" the nodes it manages. The default value is '0'.\n" . -" '0' value means include all the nodes in the subnet.\n\n" . +" the nodes it manages. And when 'sharedtftp' is disabled, nodeset handles\n" . +" boot loader configuration on a service node only for the nodes it manages.\n" . +" The default value is '0'. It means include all the nodes in the subnet.\n\n" . " pruneservices: Whether to enable service pruning when noderm is run (i.e.\n" . " removing DHCP entries when noderm is executed)\n\n" . " managedaddressmode: The mode of networking configuration during node provision.\n" . @@ -1171,9 +1172,6 @@ passed as argument rather than by table value', " in tftpdir is mounted on all on Service Nodes. Default is 1/yes.\n" . " If value is set to a hostname, the directory in tftpdir\n" . " will be mounted from that hostname on the SN\n\n" . -" disjointnetboot: Only available when sharedtftp is set to 0/no. If set to '1', a service node\n" . -" handles the netboot (petitboot/grub2/xnba) config file only for the nodes it manages.\n" . -" The default value is '0'. '0' means handle all the nodes in the same subnet.\n\n" . " sharedinstall: Indicates if a shared file system will be used for installation\n" . " resources. Possible values are: 'no', 'sns', or 'all'. 'no' \n" . " means a shared file system is not being used. 'sns' means a\n" . diff --git a/perl-xCAT/xCAT/Scope.pm b/perl-xCAT/xCAT/Scope.pm index a7aaf2588..e58d1a279 100644 --- a/perl-xCAT/xCAT/Scope.pm +++ b/perl-xCAT/xCAT/Scope.pm @@ -1,5 +1,6 @@ package xCAT::Scope; +#use Data::Dumper; use xCAT::Utils; use xCAT::Table; use xCAT::ServiceNodeUtils qw(getSNList); @@ -129,12 +130,12 @@ sub get_parallel_scope { Arguments: Reference of request - Callback: TODO, Optional, the Callback will be used to filter the nodes + SN list: Array of target service nodes Returns: An array of requests Error: none Example: - my $reqs = xCAT::Scope->get_broadcast_scope($request); + my $reqs = xCAT::Scope->get_broadcast_scope_with_parallel($request, \@snlist); =cut #----------------------------------------------------------------------------- @@ -146,18 +147,19 @@ sub get_broadcast_scope_with_parallel { #Exit if the packet has been preprocessed in its history if ($req->{_xcatpreprocessed}->[0] == 1) { return [$req]; } + my $snlist = shift; #Handle the one for current management/service node my $reqs = get_parallel_scope($req); my @requests = @$reqs; #Broadcast the request to other management/service nodes - foreach (xCAT::ServiceNodeUtils->getSNList()) { - if (xCAT::NetworkUtils->thishostisnot($_)) { - my $xcatdest = $_; + foreach (@$snlist) { + my $xcatdest = $_; + if (xCAT::NetworkUtils->thishostisnot($xcatdest)) { my $reqcopy = {%$req}; - $reqcopy->{'_xcatdest'} = $_; + $reqcopy->{'_xcatdest'} = $xcatdest; $reqcopy->{_xcatpreprocessed}->[0] = 1; - #Apply callback to filter the node range in future. + $reqs = get_parallel_scope($reqcopy); foreach (@$reqs) { push @requests, {%$_}; @@ -167,6 +169,59 @@ sub get_broadcast_scope_with_parallel { return \@requests; } +#----------------------------------------------------------------------------- + +=head3 get_broadcast_disjoint_scope_with_parallel + + Convert a request object to an array of multiple requests according to the + splitted node range. (Work under disjoint mode) + + Arguments: + Reference of request + SN hash: Hash of target service nodes => Managed CNs + Returns: An array of requests + Error: + none + Example: + my $reqs = xCAT::Scope->get_broadcast_disjoint_scope_with_parallel($request, \@snhash); +=cut + +#----------------------------------------------------------------------------- +sub get_broadcast_disjoint_scope_with_parallel { + my $req = shift; + if ($req =~ /xCAT::Scope/) { + $req = shift; + } + #Exit if the packet has been preprocessed in its history + if ($req->{_xcatpreprocessed}->[0] == 1) { return [$req]; } + + my $sn_hash = shift; + my @reqs = (); + #Handle the one for current management/service node + if ( xCAT::Utils->isMN() ) { + $reqs = get_parallel_scope($req); + } + my @requests = @$reqs; + + #Broadcast the request to other management/service nodes + foreach (keys %$sn_hash) { + my $xcatdest = $_; + if (xCAT::NetworkUtils->thishostisnot($xcatdest)) { + my $reqcopy = {%$req}; + $reqcopy->{'_xcatdest'} = $xcatdest; + $reqcopy->{'node'} = $sn_hash->{$xcatdest}; + $reqcopy->{_xcatpreprocessed}->[0] = 1; + + $reqs = get_parallel_scope($reqcopy); + foreach (@$reqs) { + push @requests, {%$_}; + } + } + } + #print Dumper(\@requests); + return \@requests; +} + sub get_broadcast_scope { my $req = shift; diff --git a/perl-xCAT/xCAT/Usage.pm b/perl-xCAT/xCAT/Usage.pm index 4ca8093c0..1377d56ce 100755 --- a/perl-xCAT/xCAT/Usage.pm +++ b/perl-xCAT/xCAT/Usage.pm @@ -481,7 +481,7 @@ Options: "Usage: Common: nodeset [-h|--help|-v|--version] - nodeset [shell|boot|runcmd=bmcsetup|osimage[=]|offline|shutdown|stat]", + nodeset [shell|boot|runcmd=bmcsetup|osimage[=]|offline|shutdown|stat [-a]]", "rmflexnode" => "Usage: rmflexnode [-h|--help|-v|--version] diff --git a/xCAT-client/pods/man8/nodeset.8.pod b/xCAT-client/pods/man8/nodeset.8.pod index 15618d46d..2fd8bc957 100644 --- a/xCAT-client/pods/man8/nodeset.8.pod +++ b/xCAT-client/pods/man8/nodeset.8.pod @@ -4,7 +4,7 @@ B - set the boot state for a noderange =head1 B -B I [B | B | B | B | B[=I] | B | B] +B I [B | B [B<-a>]| B | B | B[=I] | B | B] B I B[=I] [B<--noupdateinitrd>] [B<--ignorekernelchk>] @@ -68,7 +68,7 @@ If you would like to run a task after deployment, you can define that task with =item B -Display the current boot loader config file description for the nodes requested +Display the current boot loader config file description for the nodes requested. When B is set, using B<-a> to display them on all available service nodes. =item B diff --git a/xCAT-server/lib/xcat/plugins/grub2.pm b/xCAT-server/lib/xcat/plugins/grub2.pm index cbe35783f..4820f4307 100644 --- a/xCAT-server/lib/xcat/plugins/grub2.pm +++ b/xCAT-server/lib/xcat/plugins/grub2.pm @@ -174,9 +174,9 @@ sub setstate { $kern->{kcmdline} .= " " . $cmdhashref->{volatile}; } - my $pcfg; - unless (-d "$tftpdir/boot/grub2") { - mkpath("$tftpdir/boot/grub2"); + my $bootloader_root = "$tftpdir/boot/grub2"; + unless (-d "$bootloader_root") { + mkpath("$bootloader_root"); } my $nodemac; my %client_nethash = xCAT::DBobjUtils->getNetwkInfo([$node]); @@ -184,9 +184,10 @@ sub setstate { my $cref = $chainhash{$node}->[0]; #$chaintab->getNodeAttribs($node,['currstate']); # remove the old boot configuration files and create a new one, but only if not offline directive - system("find $tftpdir/boot/grub2/ -inum \$(stat --printf \%i $tftpdir/boot/grub2/$node 2>/dev/null) -exec rm -f {} \\; 2>/dev/null"); + system("find $bootloader_root/ -inum \$(stat --printf \%i $bootloader_root/$node 2>/dev/null) -exec rm -f {} \\; 2>/dev/null"); + my $pcfg; if ($cref and $cref->{currstate} ne "offline") { - open($pcfg, '>', $tftpdir . "/boot/grub2/" . $node); + open($pcfg, '>', "$bootloader_root/" . $node); print $pcfg "#" . $cref->{currstate} . "\n"; if (($::XCATSITEVALS{xcatdebugmode} eq "1") or ($::XCATSITEVALS{xcatdebugmode} eq "2")) { @@ -292,11 +293,6 @@ sub setstate { print $pcfg "}"; close($pcfg); } - my $inetn = xCAT::NetworkUtils->getipaddr($node); - unless ($inetn) { - syslog("local1|err", "xCAT unable to resolve IP for $node in grub2 plugin"); - return; - } } else { close($pcfg); } @@ -332,9 +328,9 @@ sub setstate { my $pname = "grub.cfg-" . sprintf("%02X%02X%02X%02X", @ipa); # remove the old boot configuration file and copy (link) a new one, but only if not offline directive - unlink($tftpdir . "/boot/grub2/" . $pname); + unlink("$bootloader_root/" . $pname); if ($cref and $cref->{currstate} ne "offline") { - link($tftpdir . "/boot/grub2/" . $node, $tftpdir . "/boot/grub2/" . $pname); + link("$bootloader_root/" . $node, "$bootloader_root/" . $pname); } } @@ -357,9 +353,9 @@ sub setstate { my $pname = "grub.cfg-01-" . $tmp; # remove the old boot configuration file and copy (link) a new one, but only if not offline directive - unlink($tftpdir . "/boot/grub2/" . $pname); + unlink("$bootloader_root/" . $pname); if ($cref and $cref->{currstate} ne "offline") { - link($tftpdir . "/boot/grub2/" . $node, $tftpdir . "/boot/grub2/" . $pname); + link("$bootloader_root/" . $node, "$bootloader_root/" . $pname); } } return; @@ -400,12 +396,14 @@ sub preprocess_request { #use Getopt::Long; my $HELP; + my $ALLFLAG; my $VERSION; my $VERBOSE; Getopt::Long::Configure("bundling"); Getopt::Long::Configure("pass_through"); if (!GetOptions('h|?|help' => \$HELP, 'v|version' => \$VERSION, + 'a' =>\$ALLFLAG, 'V' => \$VERBOSE #>>>>>>>used for trace log>>>>>>> )) { if ($usage{$command}) { @@ -467,12 +465,12 @@ sub preprocess_request { xCAT::ServiceNodeUtils->getSNandCPnodes(\@$nodes, \@SN, \@CN); unless (($args[0] eq 'stat') or ($args[0] eq 'enact')) { if ((@SN > 0) && (@CN > 0)) { # there are both SN and CN - my $rsp; - $rsp->{data}->[0] = + my %rsp; + $rsp{errorcode}->[0] = 1; + $rsp{error}->[0] = "Nodeset was run with a noderange containing both service nodes and compute nodes. This is not valid. You must submit with either compute nodes in the noderange or service nodes. \n"; - xCAT::MsgUtils->message("E", $rsp, $callback1); + $callback1->(\%rsp); return; - } } @@ -480,8 +478,28 @@ sub preprocess_request { if ($req->{inittime}->[0]) { return [$req]; } - if (@CN > 0) { # if compute nodes broadcast to all servicenodes - return xCAT::Scope->get_broadcast_scope_with_parallel($req); + if (@CN > 0) { # if compute nodes only, then broadcast to servic enodes + + my @sn = xCAT::ServiceNodeUtils->getSNList(); + unless ( @sn > 0 ) { + return xCAT::Scope->get_parallel_scope($req) + } + + my $mynodeonly = 0; + my @entries = xCAT::TableUtils->get_site_attribute("disjointdhcps"); + my $t_entry = $entries[0]; + if (defined($t_entry)) { + $mynodeonly = $t_entry; + } + $req->{'_disjointmode'} = [$mynodeonly]; + xCAT::MsgUtils->trace(0, "d", "grub2: disjointdhcps=$mynodeonly"); + + if ($mynodeonly == 0 || $ALLFLAG) { # broadcast to all service nodes + return xCAT::Scope->get_broadcast_scope_with_parallel($req, \@sn); + } + + my $sn_hash = xCAT::ServiceNodeUtils->getSNformattedhash(\@CN, "xcat", "MN"); + return xCAT::Scope->get_broadcast_disjoint_scope_with_parallel($req, $sn_hash); } } # Do not dispatch to service nodes if non-sharedtftp or the node range contains only SNs. @@ -495,19 +513,16 @@ sub process_request { $sub_req = shift; my $command = $request->{command}->[0]; %breaknetbootnodes = (); - %normalnodes = (); + %normalnodes = (); # It will be fill-up by method: setstate. my @args; - my @nodes; - my @rnodes; - #>>>>>>>used for trace log start>>>>>>> my %opt; my $verbose_on_off = 0; - if (ref($::XNBA_request->{arg})) { - @args = @{ $::XNBA_request->{arg} }; + if (ref($request->{arg})) { + @args = @{ $request->{arg} }; } else { - @args = ($::XNBA_request->{arg}); + @args = ($request->{arg}); } @ARGV = @args; GetOptions('V' => \$opt{V}); @@ -515,6 +530,10 @@ sub process_request { #>>>>>>>used for trace log end>>>>>>> + my @hostinfo = xCAT::NetworkUtils->determinehostname(); + $::myxcatname = $hostinfo[-1]; + xCAT::MsgUtils->trace($verbose_on_off, "d", "grub2: running on $::myxcatname"); + my @rnodes; if (ref($request->{node})) { @rnodes = @{ $request->{node} }; } else { @@ -527,104 +546,101 @@ sub process_request { return; } - my @hostinfo = xCAT::NetworkUtils->determinehostname(); - $::myxcatname = $hostinfo[-1]; - xCAT::MsgUtils->trace(0, "d", "grub2: running on $::myxcatname"); + if ($args[0] eq 'stat') { + my $noderestab = xCAT::Table->new('noderes'); #in order to detect per-node tftp directories + my %nrhash = %{ $noderestab->getNodesAttribs(\@rnodes, [qw(tftpdir)]) }; + foreach my $node (@rnodes) { + my %response; + my $tftpdir; + if ($nrhash{$node}->[0] and $nrhash{$node}->[0]->{tftpdir}) { + $tftpdir = $nrhash{$node}->[0]->{tftpdir}; + } else { + $tftpdir = $globaltftpdir; + } + $response{node}->[0]->{name}->[0] = $node; + $response{node}->[0]->{data}->[0] = getstate($node, $tftpdir); + $callback->(\%response); + } + return; + } - my @unmanagednodes = (); - #if not shared tftpdir, then broadcast, otherwise, set up everything + my @nodes = (); + # Filter those nodes which have bad DNS: not resolvable or inconsistent IP + my %failurenodes = (); + my %preparednodes = (); + foreach (@rnodes) { + my $ipret = xCAT::NetworkUtils->checkNodeIPaddress($_); + my $errormsg = $ipret->{'error'}; + my $nodeip = $ipret->{'ip'}; + if ($errormsg) {# Add the node to failure set + xCAT::MsgUtils->trace(0, "E", "grub2: IP address of $_ is $nodeip. $errormsg"); + unless ($nodeip) { + $failurenodes{$_} = 1; + } + } + if ($nodeip) { + $preparednodes{$_} = $nodeip; + } + } + + #if not shared tftpdir, then filter, otherwise, set up everything if ($request->{'_disparatetftp'}->[0]) { #reading hint from preprocess_command - @nodes = (); - - my %iphash = (); - # flag the IPs or names in iphash - foreach (@hostinfo) { $iphash{$_} = 1; } - #print Dumper(\%iphash); - - my $mynodeonly = 0; - my @entries = xCAT::TableUtils->get_site_attribute("disjointnetboot"); - my $t_entry = $entries[0]; - if (defined($t_entry)) { - $mynodeonly = $t_entry; - } - xCAT::MsgUtils->trace($verbose_on_off, "d", "grub2: disjointnetboot=$mynodeonly"); - - # Get managed node list under current server - # The node will be under under 'site.master' if no 'noderes.servicenode' is defined - my $sn_hash = xCAT::ServiceNodeUtils->getSNformattedhash(\@rnodes, "xcat", "MN"); - #print Dumper($sn_hash); - my %managed = (); - foreach (keys %$sn_hash) { - if (exists($iphash{$_})) { - my $cur_xmaster = $_; - foreach (@{ $sn_hash->{$cur_xmaster} }) { $managed{$_} = 1; } - last; - } - } - - my $notsamenet_nodes_err = ''; - my $notsamenet_nodes_warn = ''; - - foreach (@rnodes) { - # For MN, the scope is all CN, for SN, the scope is the nodes it managed if disjointnetboot is set. - my $req2manage = exists($managed{$_}); - if ($req2manage) { - push @unmanagednodes, $_; - # quick pass through if disjoint is set. - next if ( $mynodeonly == 1 && xCAT::Utils->isMN() != 1 ); - } - + # Filter those nodes not in the same subnet, and print error message in log file. + foreach (keys %preparednodes) { # Only handle its boot configuration files if the node in same subnet - if (xCAT::NetworkUtils->nodeonmynet($_)) { + if (xCAT::NetworkUtils->nodeonmynet($preparednodes{$_})) { push @nodes, $_; - } elsif ( $req2manage ) { - # report error when it is under my control but I cannot handle it. - $notsamenet_nodes_err .= " $_"; - } - else { - $notsamenet_nodes_warn .= " $_"; - } - } - - if ( $mynodeonly == 1 && scalar (@unmanagednodes) > 0 && xCAT::Utils->isMN() != 1) { - my $str_umnodes = join(" ", @unmanagednodes); - xCAT::MsgUtils->trace($verbose_on_off, "d", "grub2: unmanaged nodes are $str_umnodes"); - } - - if ( $notsamenet_nodes_err || $notsamenet_nodes_warn ) { - my $msg = "grub2 configuration file was not created "; - $msg .= "on $::myxcatname " if ( $::myxcatname ); - $msg .= "for below nodes because sharedtftp attribute is not set and the nodes are not on same network as this xcatmaster: "; - xCAT::MsgUtils->message("S", $msg . $notsamenet_nodes_warn . $notsamenet_nodes_err); - # For managed children, need to report error - if ( $notsamenet_nodes_err ) { - my $rsp; - $rsp->{data}->[0] = $msg . $notsamenet_nodes_err; - xCAT::MsgUtils->message("E", $rsp, $callback); + } else { + xCAT::MsgUtils->trace(0, "W", "grub2: configuration file was not created for [$_] because the node is not on the same network as this server"); + delete $preparednodes{$_}; } } } else { - @nodes = @rnodes; + @nodes = keys %preparednodes; } - #>>>>>>>used for trace log>>>>>>> my $str_node = join(" ", @nodes); xCAT::MsgUtils->trace($verbose_on_off, "d", "grub2: nodes are $str_node") if ($str_node); # return directly if no nodes in the same network unless (@nodes) { xCAT::MsgUtils->message("S", "xCAT: grub2 netboot: no valid nodes. Stop the operation on this server."); + + # It must be an error if my managed nodes are not handled. + if (xCAT::Utils->isMN() != 1 && $request->{'_disparatetftp'}->[0] && $request->{'_disjointmode'}->[0] != 1) { + # Find out which nodes are really mine only when not sharedtftp and not disjoint mode. + # For other case, all passing node range are required to be handled. + my %iphash = (); + # flag the IPs or names in iphash + foreach (@hostinfo) { $iphash{$_} = 1; } + + # Get managed node list under current server + # The node will be under under 'site.master' if no 'noderes.servicenode' is defined + my $sn_hash = xCAT::ServiceNodeUtils->getSNformattedhash(\@rnodes, "xcat", "MN"); + #my %managed = (); + my $req2manage = 0; + foreach (keys %$sn_hash) { + if (exists($iphash{$_})) { + #my $cur_xmaster = $_; + #foreach (@{ $sn_hash->{$cur_xmaster} }) { $managed{$_} = 1; } + $req2manage = 1; + last; + } + } + if ($req2manage == 0) { + xCAT::MsgUtils->trace(0, "d", "grub2: No nodes are required to be managed on this server"); + return; + } + } + my $rsp; + $rsp->{errorcode}->[0] = 1; + $rsp->{error}->[0] = "Failed to generate grub2 configurations for some node(s) on $::myxcatname. Check xCAT log file for more details.\n"; + $callback->($rsp); return; } - if (ref($request->{arg})) { - @args = @{ $request->{arg} }; - } else { - @args = ($request->{arg}); - } - #now run the begin part of the prescripts - unless ($args[0] eq 'stat') { # or $args[0] eq 'enact') { + unless ($args[0] eq '') { # or $args[0] eq 'enact') { $errored = 0; if ($request->{'_disparatetftp'}->[0]) { #the call is distrubuted to the service node already, so only need to handle my own children xCAT::MsgUtils->trace($verbose_on_off, "d", "grub2: the call is distrubuted to the service node already, so only need to handle my own children"); @@ -654,7 +670,7 @@ sub process_request { if (!$inittime) { $inittime = 0; } my %bphash; - unless ($args[0] eq 'stat') { # or $args[0] eq 'enact') { + unless ($args[0] eq '') { # or $args[0] eq 'enact') { $errored = 0; xCAT::MsgUtils->trace($verbose_on_off, "d", "grub2: issue setdestiny request"); $sub_req->({ command => ['setdestiny'], @@ -669,6 +685,7 @@ sub process_request { } } + xCAT::MsgUtils->trace($verbose_on_off, "d", "grub2: starting to handle configuration..."); my $chaintab = xCAT::Table->new('chain', -create => 1); my $chainhash = $chaintab->getNodesAttribs(\@nodes, ['currstate']); my $noderestab = xCAT::Table->new('noderes', -create => 1); @@ -694,10 +711,7 @@ sub process_request { $tftpdir = $globaltftpdir; } $response{node}->[0]->{name}->[0] = $_; - if ($args[0] eq 'stat') { - $response{node}->[0]->{data}->[0] = getstate($_, $tftpdir); - $callback->(\%response); - } elsif ($args[0]) { #If anything else, send it on to the destiny plugin, then setstate + if ($args[0]) { # Send it on to the destiny plugin, then setstate my $ent = $typehash->{$_}->[0]; my $osimgname = $ent->{'provmethod'}; my $linuximghash = undef; @@ -713,11 +727,11 @@ sub process_request { } } } # end of foreach node + xCAT::MsgUtils->trace($verbose_on_off, "d", "grub2: Finish to handle configurations"); my @normalnodeset = keys %normalnodes; my @breaknetboot = keys %breaknetbootnodes; - #print "grub2 :inittime=$inittime; normalnodeset=@normalnodeset; breaknetboot=@breaknetboot\n"; my %osimagenodehash; for my $nn (@normalnodeset) { @@ -738,7 +752,7 @@ sub process_request { } #Don't bother to try dhcp binding changes if sub_req not passed, i.e. service node build time - unless (($args[0] eq 'stat') || ($inittime) || ($args[0] eq 'offline')) { + unless (($inittime) || ($args[0] eq 'offline')) { foreach my $osimage (keys %osimagenodehash) { #TOTO check the existence of grub2 executable files for corresponding arch @@ -838,7 +852,7 @@ sub process_request { } #now run the end part of the prescripts - unless ($args[0] eq 'stat') { # or $args[0] eq 'enact') + unless ($args[0] eq '') { # or $args[0] eq 'enact') $errored = 0; if ($request->{'_disparatetftp'}->[0]) { #the call is distrubuted to the service node already, so only need to handles my own children xCAT::MsgUtils->trace($verbose_on_off, "d", "grub2: issue runendpre request"); @@ -859,6 +873,16 @@ sub process_request { return; } } + + # Return error codes if there are failed nodes + if (%failurenodes) { + my $rsp; + $rsp->{errorcode}->[0] = 1; + $rsp->{error}->[0] = "Failed to generate grub2 configurations for some node(s) on $::myxcatname. Check xCAT log file for more details.\n"; + $callback->($rsp); + return; + } + } #---------------------------------------------------------------------------- diff --git a/xCAT-server/lib/xcat/plugins/petitboot.pm b/xCAT-server/lib/xcat/plugins/petitboot.pm index 7b9487da3..89c02fd3b 100644 --- a/xCAT-server/lib/xcat/plugins/petitboot.pm +++ b/xCAT-server/lib/xcat/plugins/petitboot.pm @@ -79,7 +79,7 @@ sub setstate { =pod - This function will manipulate the yaboot structure to match what the noderes/chain tables indicate the node should be booting. + This function will manipulate the petitboot structure to match what the noderes/chain tables indicate the node should be booting. =cut @@ -169,18 +169,19 @@ sub setstate { } } - my $pcfg; - unless (-d "$tftpdir/petitboot") { - mkpath("$tftpdir/petitboot"); + my $bootloader_root = "$tftpdir/petitboot"; + unless (-d "$bootloader_root") { + mkpath("$bootloader_root"); } my $nodemac; my $cref = $chainhash{$node}->[0]; #$chaintab->getNodeAttribs($node,['currstate']); + my $pcfg; # remove the old boot configuration file and create a new one, but only if not offline directive - unlink($tftpdir . "/petitboot/" . $node); + unlink("$bootloader_root/" . $node); if ($cref and $cref->{currstate} ne "offline") { - open($pcfg, '>', $tftpdir . "/petitboot/" . $node); + open($pcfg, '>', "$bootloader_root/" . $node); print $pcfg "#" . $cref->{currstate} . "\n"; } $normalnodes{$node} = 1; #Assume a normal netboot (well, normal dhcp, @@ -216,18 +217,13 @@ sub setstate { print $pcfg "\tappend \"" . $kern->{kcmdline} . "\"\n"; } close($pcfg); - my $inetn = xCAT::NetworkUtils->getipaddr($node); - unless ($inetn) { - syslog("local1|err", "xCAT unable to resolve IP for $node in petitboot plugin"); - return; - } } else { #TODO: actually, should possibly default to xCAT image? #print $pcfg "bye\n"; close($pcfg); } my $ip = xCAT::NetworkUtils->getipaddr($node); unless ($ip) { - syslog("local1|err", "xCAT unable to resolve IP in petitboot plugin"); + syslog("local1|err", "xCAT unable to resolve IP for $node in petitboot plugin"); return; } @@ -236,9 +232,9 @@ sub setstate { $pname = uc($pname); # remove the old boot configuration file and copy (link) a new one, but only if not offline directive - unlink($tftpdir . "/" . $pname); + unlink("$tftpdir/" . $pname); if ($cref and $cref->{currstate} ne "offline") { - link($tftpdir . "/petitboot/" . $node, $tftpdir . "/" . $pname); + link("$bootloader_root/" . $node, "$tftpdir/" . $pname); } return; } @@ -282,12 +278,14 @@ sub preprocess_request { #use Getopt::Long; my $HELP; + my $ALLFLAG; my $VERSION; my $VERBOSE; Getopt::Long::Configure("bundling"); Getopt::Long::Configure("pass_through"); if (!GetOptions('h|?|help' => \$HELP, 'v|version' => \$VERSION, + 'a' =>\$ALLFLAG, 'V' => \$VERBOSE #>>>>>>>used for trace log>>>>>>> )) { if ($usage{$command}) { @@ -333,6 +331,13 @@ sub preprocess_request { return; } + if ($ARGV[0] ne "stat" && $ALLFLAG) { + my %rsp; + $rsp{error}->[0] = "'-a' could only be used with 'stat' subcommand."; + $rsp{errorcode}->[0] = 1; + $callback1->(\%rsp); + return; + } #Assume shared tftp directory for boring people, but for cool people, help sync up tftpdirectory contents when #if they specify no sharedtftp in site table @@ -345,21 +350,43 @@ sub preprocess_request { my @SN; my @CN; xCAT::ServiceNodeUtils->getSNandCPnodes(\@$nodes, \@SN, \@CN); - if ((@SN > 0) && (@CN > 0)) { # there are both SN and CN - my $rsp; - $rsp->{data}->[0] = -"Nodeset was run with a noderange containing both service nodes and compute nodes. This is not valid. You must submit with either compute nodes in the noderange or service nodes. \n"; - xCAT::MsgUtils->message("E", $rsp, $callback1); - return; - + unless (($args[0] eq 'stat') or ($args[0] eq 'enact')) { + if ((@SN > 0) && (@CN > 0)) { # there are both SN and CN + my %rsp; + $rsp{errorcode}->[0] = 1; + $rsp{error}->[0] = + "Nodeset was run with a noderange containing both service nodes and compute nodes. This is not valid. You must submit with either compute nodes in the noderange or service nodes. \n"; + $callback1->(\%rsp); + return; + } } $req->{'_disparatetftp'} = [1]; if ($req->{inittime}->[0]) { return [$req]; } - if (@CN > 0) { # if compute nodes broadcast to all servicenodes - return xCAT::Scope->get_broadcast_scope_with_parallel($req); + if (@CN > 0) { # if compute nodes only, then broadcast to servic enodes + + my @sn = xCAT::ServiceNodeUtils->getSNList(); + unless ( @sn > 0 ) { + return xCAT::Scope->get_parallel_scope($req) + } + + my $mynodeonly = 0; + my @entries = xCAT::TableUtils->get_site_attribute("disjointdhcps"); + my $t_entry = $entries[0]; + if (defined($t_entry)) { + $mynodeonly = $t_entry; + } + $req->{'_disjointmode'} = [$mynodeonly]; + xCAT::MsgUtils->trace(0, "d", "petitboot: disjointdhcps=$mynodeonly"); + + if ($mynodeonly == 0 || $ALLFLAG) { # broadcast to all service nodes + return xCAT::Scope->get_broadcast_scope_with_parallel($req, \@sn); + } + + my $sn_hash = xCAT::ServiceNodeUtils->getSNformattedhash(\@CN, "xcat", "MN"); + return xCAT::Scope->get_broadcast_disjoint_scope_with_parallel($req, $sn_hash); } } # Do not dispatch to service nodes if non-sharedtftp or the node range contains only SNs. @@ -374,16 +401,16 @@ sub process_request { $sub_req = shift; my $command = $request->{command}->[0]; %breaknetbootnodes = (); - %normalnodes = (); + %normalnodes = (); # It will be fill-up by method: setstate. #>>>>>>>used for trace log start>>>>>>> my @args = (); my %opt; my $verbose_on_off = 0; - if (ref($::request->{arg})) { - @args = @{ $::request->{arg} }; + if (ref($request->{arg})) { + @args = @{ $request->{arg} }; } else { - @args = ($::request->{arg}); + @args = ($request->{arg}); } @ARGV = @args; GetOptions('V' => \$opt{V}); @@ -394,7 +421,9 @@ sub process_request { if ($::XCATSITEVALS{"httpmethod"}) { $httpmethod = $::XCATSITEVALS{"httpmethod"}; } if ($::XCATSITEVALS{"httpport"}) { $httpport = $::XCATSITEVALS{"httpport"}; } - my @nodes; + my @hostinfo = xCAT::NetworkUtils->determinehostname(); + $::myxcatname = $hostinfo[-1]; + xCAT::MsgUtils->trace($verbose_on_off, "d", "petitboot: running on $::myxcatname"); my @rnodes; if (ref($request->{node})) { @rnodes = @{ $request->{node} }; @@ -408,104 +437,101 @@ sub process_request { return; } - my @hostinfo = xCAT::NetworkUtils->determinehostname(); - $::myxcatname = $hostinfo[-1]; - xCAT::MsgUtils->trace(0, "d", "petitboot: running on $::myxcatname"); - - my @unmanagednodes = (); - #if not shared tftpdir, then broadcast, otherwise, set up everything - if ($request->{'_disparatetftp'}->[0]) { #reading hint from preprocess_command - @nodes = (); - - my %iphash = (); - # flag the IPs or names in iphash - foreach (@hostinfo) { $iphash{$_} = 1; } - #print Dumper(\%iphash); - - my $mynodeonly = 0; - my @entries = xCAT::TableUtils->get_site_attribute("disjointnetboot"); - my $t_entry = $entries[0]; - if (defined($t_entry)) { - $mynodeonly = $t_entry; - } - xCAT::MsgUtils->trace($verbose_on_off, "d", "petitboot: disjointnetboot=$mynodeonly"); - - # Get managed node list under current server - # The node will be under under 'site.master' if no 'noderes.servicenode' is defined - my $sn_hash = xCAT::ServiceNodeUtils->getSNformattedhash(\@rnodes, "xcat", "MN"); - #print Dumper($sn_hash); - my %managed = (); - foreach (keys %$sn_hash) { - if (exists($iphash{$_})) { - my $cur_xmaster = $_; - foreach (@{ $sn_hash->{$cur_xmaster} }) { $managed{$_} = 1; } - last; + if ($args[0] eq 'stat') { + my $noderestab = xCAT::Table->new('noderes'); #in order to detect per-node tftp directories + my %nrhash = %{ $noderestab->getNodesAttribs(\@rnodes, [qw(tftpdir)]) }; + foreach my $node (@rnodes) { + my %response; + my $tftpdir; + if ($nrhash{$node}->[0] and $nrhash{$node}->[0]->{tftpdir}) { + $tftpdir = $nrhash{$node}->[0]->{tftpdir}; + } else { + $tftpdir = $globaltftpdir; } + $response{node}->[0]->{name}->[0] = $node; + $response{node}->[0]->{data}->[0] = getstate($node, $tftpdir); + $callback->(\%response); } - - my $notsamenet_nodes_err = ''; - my $notsamenet_nodes_warn = ''; - - foreach (@rnodes) { - # For MN, the scope is all CN, for SN, the scope is the nodes it managed if disjointnetboot is set. - my $req2manage = exists($managed{$_}); - if ($req2manage) { - push @unmanagednodes, $_; - # quick pass through if disjoint is set. - next if ( $mynodeonly == 1 && xCAT::Utils->isMN() != 1 ); - } - - # Only handle its boot configuration files if the node in same subnet - if (xCAT::NetworkUtils->nodeonmynet($_)) { - push @nodes, $_; - } elsif ( $req2manage ) { - # report error when it is under my control but I cannot handle it. - $notsamenet_nodes_err .= " $_"; - } - else { - $notsamenet_nodes_warn .= " $_"; - } - } - - if ( $mynodeonly == 1 && scalar (@unmanagednodes) > 0 && xCAT::Utils->isMN() != 1) { - my $str_umnodes = join(" ", @unmanagednodes); - xCAT::MsgUtils->trace($verbose_on_off, "d", "petitboot: unmanaged nodes are $str_umnodes"); - } - - if ( $notsamenet_nodes_err || $notsamenet_nodes_warn ) { - my $msg = "petitboot configuration file was not created "; - $msg .= "on $::myxcatname " if ( $::myxcatname ); - $msg .= "for below nodes because sharedtftp attribute is not set and the nodes are not on same network as this xcatmaster: "; - xCAT::MsgUtils->message("S", $msg . $notsamenet_nodes_warn . $notsamenet_nodes_err); - # For managed children, need to report error - if ( $notsamenet_nodes_err ) { - my $rsp; - $rsp->{data}->[0] = $msg . $notsamenet_nodes_err; - xCAT::MsgUtils->message("E", $rsp, $callback); - } - } - } else { - @nodes = @rnodes; - } - - #>>>>>>>used for trace log>>>>>>> - my $str_node = join(" ", @nodes); - xCAT::MsgUtils->trace($verbose_on_off, "d", "petitboot: nodes are $str_node") if ($str_node); - - # return directly if no nodes in the same network - unless (@nodes) { - xCAT::MsgUtils->message("S", "xCAT: petitboot netboot: no valid nodes. Stop the operation on this server."); return; } - if (ref($request->{arg})) { - @args = @{ $request->{arg} }; + my @nodes = (); + # Filter those nodes which have bad DNS: not resolvable or inconsistent IP + my %failurenodes = (); + my %preparednodes = (); + foreach (@rnodes) { + my $ipret = xCAT::NetworkUtils->checkNodeIPaddress($_); + my $errormsg = $ipret->{'error'}; + my $nodeip = $ipret->{'ip'}; + if ($errormsg) {# Add the node to failure set + xCAT::MsgUtils->trace(0, "E", "petitboot: IP address of $_ is $nodeip. $errormsg"); + unless ($nodeip) { + $failurenodes{$_} = 1; + } + } + if ($nodeip) { + $preparednodes{$_} = $nodeip; + } + } + + #if not shared tftpdir, then filter, otherwise, set up everything + if ($request->{'_disparatetftp'}->[0]) { #reading hint from preprocess_command + # Filter those nodes not in the same subnet, and print error message in log file. + foreach (keys %preparednodes) { + # Only handle its boot configuration files if the node in same subnet + if (xCAT::NetworkUtils->nodeonmynet($preparednodes{$_})) { + push @nodes, $_; + } else { + xCAT::MsgUtils->trace(0, "W", "petitboot: configuration file was not created for [$_] because the node is not on the same network as this server"); + delete $preparednodes{$_}; + } + } } else { - @args = ($request->{arg}); + @nodes = keys %preparednodes; + } + + my $str_node = join(" ", @nodes); + xCAT::MsgUtils->trace($verbose_on_off, "d", "petitboot: nodes are $str_node") if ($str_node); + + # Return directly if no nodes in the same network + unless (@nodes) { + xCAT::MsgUtils->message("S", "xCAT: petitboot netboot: no valid nodes. Stop the operation on this server."); + + # It must be an error if my managed nodes are not handled. + if (xCAT::Utils->isMN() != 1 && $request->{'_disparatetftp'}->[0] && $request->{'_disjointmode'}->[0] != 1) { + # Find out which nodes are really mine only when not sharedtftp and not disjoint mode. + # For other case, all passing node range are required to be handled. + my %iphash = (); + # flag the IPs or names in iphash + foreach (@hostinfo) { $iphash{$_} = 1; } + + # Get managed node list under current server + # The node will be under under 'site.master' if no 'noderes.servicenode' is defined + my $sn_hash = xCAT::ServiceNodeUtils->getSNformattedhash(\@rnodes, "xcat", "MN"); + #my %managed = (); + my $req2manage = 0; + foreach (keys %$sn_hash) { + if (exists($iphash{$_})) { + #my $cur_xmaster = $_; + #foreach (@{ $sn_hash->{$cur_xmaster} }) { $managed{$_} = 1; } + $req2manage = 1; + last; + } + } + if ($req2manage == 0) { + xCAT::MsgUtils->trace(0, "d", "petitboot: No nodes are required to be managed on this server"); + return; + } + } + my $rsp; + $rsp->{errorcode}->[0] = 1; + $rsp->{error}->[0] = "Failed to generate petitboot configurations for some node(s) on $::myxcatname. Check xCAT log file for more details.\n"; + $callback->($rsp); + return; } #now run the begin part of the prescripts - unless ($args[0] eq 'stat') { # or $args[0] eq 'enact') { + unless ($args[0] eq '') { # or $args[0] eq 'enact') { $errored = 0; if ($request->{'_disparatetftp'}->[0]) { #the call is distrubuted to the service node already, so only need to handle my own children xCAT::MsgUtils->trace($verbose_on_off, "d", "petitboot: the call is distrubuted to the service node already, so only need to handle my own children"); @@ -517,7 +543,7 @@ sub process_request { xCAT::MsgUtils->trace($verbose_on_off, "d", "petitboot: nodeset did not distribute to the service node"); xCAT::MsgUtils->trace($verbose_on_off, "d", "petitboot: issue runbeginpre request"); $sub_req->({ command => ['runbeginpre'], - node => \@rnodes, + node => \@nodes, arg => [ $args[0] ] }, \&pass_along); } if ($errored) { @@ -535,7 +561,7 @@ sub process_request { if (!$inittime) { $inittime = 0; } my %bphash; - unless ($args[0] eq 'stat') { # or $args[0] eq 'enact') { + unless ($args[0] eq '') { # or $args[0] eq 'enact') { $errored = 0; xCAT::MsgUtils->trace($verbose_on_off, "d", "petitboot: issue setdestiny request"); $sub_req->({ command => ['setdestiny'], @@ -561,6 +587,8 @@ sub process_request { }); xCAT::MsgUtils->message("S", "xCAT: petitboot netboot: clear node(s): @nodes boot device setting."); } + + xCAT::MsgUtils->trace($verbose_on_off, "d", "petitboot: starting to handle configuration..."); my $chaintab = xCAT::Table->new('chain', -create => 1); my $chainhash = $chaintab->getNodesAttribs(\@nodes, ['currstate']); my $noderestab = xCAT::Table->new('noderes', -create => 1); @@ -584,13 +612,10 @@ sub process_request { $tftpdir = $globaltftpdir; } $response{node}->[0]->{name}->[0] = $_; - if ($args[0] eq 'stat') { - $response{node}->[0]->{data}->[0] = getstate($_, $tftpdir); - $callback->(\%response); - } elsif ($args[0]) { #If anything else, send it on to the destiny plugin, then setstate + if ($args[0]) { # send it on to the destiny plugin, then setstate my $ent = $typehash->{$_}->[0]; my $osimgname = $ent->{'provmethod'}; - my $linuximghash = $linuximghash = $linuximgtab->getAttribs({ imagename => $osimgname }, 'boottarget', 'addkcmdline'); + my $linuximghash = $linuximgtab->getAttribs({ imagename => $osimgname }, 'boottarget', 'addkcmdline'); ($rc, $errstr) = setstate($_, \%bphash, $chainhash, $machash, $tftpdir, $nodereshash, $linuximghash); @@ -601,11 +626,10 @@ sub process_request { } } } # end of foreach node + xCAT::MsgUtils->trace($verbose_on_off, "d", "petitboot: Finish to handle configurations"); my @normalnodeset = keys %normalnodes; my @breaknetboot = keys %breaknetbootnodes; - - #print "yaboot:inittime=$inittime; normalnodeset=@normalnodeset; breaknetboot=@breaknetboot\n"; my %osimagenodehash; for my $nn (@normalnodeset) { @@ -616,7 +640,7 @@ sub process_request { } #Don't bother to try dhcp binding changes if sub_req not passed, i.e. service node build time - unless (($args[0] eq 'stat') || ($inittime) || ($args[0] eq 'offline')) { + unless (($inittime) || ($args[0] eq 'offline')) { #dhcp stuff my $do_dhcpsetup = 1; @@ -626,16 +650,17 @@ sub process_request { if ($t_entry =~ /0|n|N/) { $do_dhcpsetup = 0; } } if ($do_dhcpsetup) { - if ($::request->{'_disparatetftp'}->[0]) { #reading hint from preprocess_command - xCAT::MsgUtils->trace($verbose_on_off, "d", "petitboot: issue makedhcp request"); - $sub_req->({ command => ['makedhcp'], arg => ['-l'], - node => \@normalnodeset }, $callback); - } else { - xCAT::MsgUtils->trace($verbose_on_off, "d", "petitboot: issue makedhcp request"); - $sub_req->({ command => ['makedhcp'], - node => \@normalnodeset }, $callback); - } + my @parameter; + push @parameter, '-l' if ($::request->{'_disparatetftp'}->[0]); + xCAT::MsgUtils->trace($verbose_on_off, "d", "petitboot: issue makedhcp request"); + + $sub_req->({ command => ['makedhcp'], + arg => \@parameter, + node => \@normalnodeset }, $callback); + } else { + xCAT::MsgUtils->trace($verbose_on_off, "d", "petitboot: dhcpsetup=$do_dhcpsetup"); } + } if ($args[0] eq 'offline') { @@ -645,7 +670,7 @@ sub process_request { } #now run the end part of the prescripts - unless ($args[0] eq 'stat') { # or $args[0] eq 'enact') + unless ($args[0] eq '') { # or $args[0] eq 'enact') $errored = 0; if ($request->{'_disparatetftp'}->[0]) { #the call is distrubuted to the service node already, so only need to handles my own children xCAT::MsgUtils->trace($verbose_on_off, "d", "petitboot: issue runendpre request"); @@ -655,7 +680,7 @@ sub process_request { } else { #nodeset did not distribute to the service node, here we need to let runednpre to distribute the nodes to their masters xCAT::MsgUtils->trace($verbose_on_off, "d", "petitboot: issue runendpre request"); $sub_req->({ command => ['runendpre'], - node => \@rnodes, + node => \@nodes, arg => [ $args[0] ] }, \&pass_along); } if ($errored) { @@ -666,6 +691,15 @@ sub process_request { return; } } + + # Return error codes if there are failed nodes + if (%failurenodes) { + my $rsp; + $rsp->{errorcode}->[0] = 1; + $rsp->{error}->[0] = "Failed to generate petitboot configurations for some node(s) on $::myxcatname. Check xCAT log file for more details.\n"; + $callback->($rsp); + return; + } } #---------------------------------------------------------------------------- diff --git a/xCAT-server/lib/xcat/plugins/xnba.pm b/xCAT-server/lib/xcat/plugins/xnba.pm index 6464a70c3..da8d8d467 100644 --- a/xCAT-server/lib/xcat/plugins/xnba.pm +++ b/xCAT-server/lib/xcat/plugins/xnba.pm @@ -331,10 +331,12 @@ sub preprocess_request { Getopt::Long::Configure("bundling"); Getopt::Long::Configure("pass_through"); my $HELP; + my $ALLFLAG; my $VERSION; my $VERBOSE; if (!GetOptions('h|?|help' => \$HELP, 'v|version' => \$VERSION, + 'a' =>\$ALLFLAG, 'V' => \$VERBOSE #>>>>>>>used for trace log>>>>>>> )) { if ($usage{$command}) { @@ -380,6 +382,13 @@ sub preprocess_request { return; } + if ($ARGV[0] ne "stat" && $ALLFLAG) { + my %rsp; + $rsp{error}->[0] = "'-a' could only be used with 'stat' subcommand."; + $rsp{errorcode}->[0] = 1; + $callback1->(\%rsp); + return; + } #Assume shared tftp directory for boring people, but for cool people, help sync up tftpdirectory contents when #they specify no sharedtftp in site table @@ -394,12 +403,12 @@ sub preprocess_request { xCAT::ServiceNodeUtils->getSNandCPnodes(\@$nodes, \@SN, \@CN); unless (($args[0] eq 'stat') or ($args[0] eq 'enact')) { # mix is ok for these options if ((@SN > 0) && (@CN > 0)) { # there are both SN and CN - my $rsp; - $rsp->{data}->[0] = + my %rsp; + $rsp{errorcode}->[0] = 1; + $rsp{error}->[0] = "Nodeset was run with a noderange containing both service nodes and compute nodes. This is not valid. You must submit with either compute nodes in the noderange or service nodes. \n"; - xCAT::MsgUtils->message("E", $rsp, $callback1); + $callback1->(\%rsp); return; - } } @@ -408,7 +417,27 @@ sub preprocess_request { return [$req]; } if (@CN > 0) { # if compute nodes broadcast to all servicenodes - return xCAT::Scope->get_broadcast_scope_with_parallel($req); + + my @sn = xCAT::ServiceNodeUtils->getSNList(); + unless ( @sn > 0 ) { + return xCAT::Scope->get_parallel_scope($req) + } + + my $mynodeonly = 0; + my @entries = xCAT::TableUtils->get_site_attribute("disjointdhcps"); + my $t_entry = $entries[0]; + if (defined($t_entry)) { + $mynodeonly = $t_entry; + } + $req->{'_disjointmode'} = [$mynodeonly]; + xCAT::MsgUtils->trace(0, "d", "xnba: disjointdhcps=$mynodeonly"); + + if ($mynodeonly == 0 || $ALLFLAG) { # broadcast to all service nodes + return xCAT::Scope->get_broadcast_scope_with_parallel($req, \@sn); + } + + my $sn_hash = xCAT::ServiceNodeUtils->getSNformattedhash(\@CN, "xcat", "MN"); + return xCAT::Scope->get_broadcast_disjoint_scope_with_parallel($req, $sn_hash); } } # Do not dispatch to service nodes if non-sharedtftp or the node range contains only SNs. @@ -438,12 +467,14 @@ sub process_request { #>>>>>>>used for trace log end>>>>>>> + my @hostinfo = xCAT::NetworkUtils->determinehostname(); + $::myxcatname = $hostinfo[-1]; + xCAT::MsgUtils->trace(0, "d", "xnba: running on $::myxcatname"); if (ref($::XNBA_request->{node})) { @rnodes = @{ $::XNBA_request->{node} }; } else { if ($::XNBA_request->{node}) { @rnodes = ($::XNBA_request->{node}); } } - unless (@rnodes) { if ($usage{ $::XNBA_request->{command}->[0] }) { $::XNBA_callback->({ data => $usage{ $::XNBA_request->{command}->[0] } }); @@ -451,104 +482,101 @@ sub process_request { return; } - my @hostinfo = xCAT::NetworkUtils->determinehostname(); - $::myxcatname = $hostinfo[-1]; - xCAT::MsgUtils->trace(0, "d", "xnba: running on $::myxcatname"); + if ($args[0] eq 'stat') { + my $noderestab = xCAT::Table->new('noderes'); #in order to detect per-node tftp directories + my %nrhash = %{ $noderestab->getNodesAttribs(\@rnodes, [qw(tftpdir)]) }; + foreach my $node (@rnodes) { + my %response; + my $tftpdir; + if ($nrhash{$node}->[0] and $nrhash{$node}->[0]->{tftpdir}) { + $tftpdir = $nrhash{$node}->[0]->{tftpdir}; + } else { + $tftpdir = $globaltftpdir; + } + $response{node}->[0]->{name}->[0] = $node; + $response{node}->[0]->{data}->[0] = getstate($node, $tftpdir); + $::XNBA_callback->(\%response); + } + return; + } - my @unmanagednodes = (); - #if not shared tftpdir, then broadcast, otherwise, set up everything + my @nodes = (); + # Filter those nodes which have bad DNS: not resolvable or inconsistent IP + my %failurenodes = (); + my %preparednodes = (); + foreach (@rnodes) { + my $ipret = xCAT::NetworkUtils->checkNodeIPaddress($_); + my $errormsg = $ipret->{'error'}; + my $nodeip = $ipret->{'ip'}; + if ($errormsg) {# Add the node to failure set + xCAT::MsgUtils->trace(0, "E", "xnba: IP address of $_ is $nodeip. $errormsg"); + unless ($nodeip) { + $failurenodes{$_} = 1; + } + } + if ($nodeip) { + $preparednodes{$_} = $nodeip; + } + } + + #if not shared tftpdir, then filter, otherwise, set up everything if ($::XNBA_request->{'_disparatetftp'}->[0]) { #reading hint from preprocess_command - @nodes = (); - - my %iphash = (); - # flag the IPs or names in iphash - foreach (@hostinfo) { $iphash{$_} = 1; } - #print Dumper(\%iphash); - - my $mynodeonly = 0; - my @entries = xCAT::TableUtils->get_site_attribute("disjointnetboot"); - my $t_entry = $entries[0]; - if (defined($t_entry)) { - $mynodeonly = $t_entry; - } - xCAT::MsgUtils->trace($verbose_on_off, "d", "xnba: disjointnetboot=$mynodeonly"); - - # Get managed node list under current server - # The node will be under under 'site.master' if no 'noderes.servicenode' is defined - my $sn_hash = xCAT::ServiceNodeUtils->getSNformattedhash(\@rnodes, "xcat", "MN"); - #print Dumper($sn_hash); - my %managed = (); - foreach (keys %$sn_hash) { - if (exists($iphash{$_})) { - my $cur_xmaster = $_; - foreach (@{ $sn_hash->{$cur_xmaster} }) { $managed{$_} = 1; } - last; - } - } - - my $notsamenet_nodes_err = ''; - my $notsamenet_nodes_warn = ''; - - foreach (@rnodes) { - # For MN, the scope is all CN, for SN, the scope is the nodes it managed if disjointnetboot is set. - my $req2manage = exists($managed{$_}); - if ($req2manage) { - push @unmanagednodes, $_; - # quick pass through if disjoint is set. - next if ( $mynodeonly == 1 && xCAT::Utils->isMN() != 1 ); - } - + # Filter those nodes not in the same subnet, and print error message in log file. + foreach (keys %preparednodes) { # Only handle its boot configuration files if the node in same subnet - if (xCAT::NetworkUtils->nodeonmynet($_)) { + if (xCAT::NetworkUtils->nodeonmynet($preparednodes{$_})) { push @nodes, $_; - } elsif ( $req2manage ) { - # report error when it is under my control but I cannot handle it. - $notsamenet_nodes_err .= " $_"; - } - else { - $notsamenet_nodes_warn .= " $_"; - } - } - - if ( $mynodeonly == 1 && scalar (@unmanagednodes) > 0 && xCAT::Utils->isMN() != 1) { - my $str_umnodes = join(" ", @unmanagednodes); - xCAT::MsgUtils->trace($verbose_on_off, "d", "xnba: unmanaged nodes are $str_umnodes"); - } - - if ( $notsamenet_nodes_err || $notsamenet_nodes_warn ) { - my $msg = "xnba configuration file was not created "; - $msg .= "on $::myxcatname " if ( $::myxcatname ); - $msg .= "for below nodes because sharedtftp attribute is not set and the nodes are not on same network as this xcatmaster: "; - xCAT::MsgUtils->message("S", $msg . $notsamenet_nodes_warn . $notsamenet_nodes_err); - # For managed children, need to report error - if ( $notsamenet_nodes_err ) { - my $rsp; - $rsp->{data}->[0] = $msg . $notsamenet_nodes_err; - xCAT::MsgUtils->message("E", $rsp, $::XNBA_callback); + } else { + xCAT::MsgUtils->trace(0, "W", "xnba: configuration file was not created for [$_] because the node is not on the same network as this server"); + delete $preparednodes{$_}; } } } else { - @nodes = @rnodes; + @nodes = keys %preparednodes; } - #>>>>>>>used for trace log>>>>>>> my $str_node = join(" ", @nodes); xCAT::MsgUtils->trace(0, "d", "xnba: nodes are $str_node") if ($str_node); # return directly if no nodes in the same network unless (@nodes) { xCAT::MsgUtils->message("S", "xCAT: xnba netboot: no valid nodes. Stop the operation on this server."); + + # It must be an error if my managed nodes are not handled. + if (xCAT::Utils->isMN() != 1 && $::XNBA_request->{'_disparatetftp'}->[0] && $::XNBA_request->{'_disjointmode'}->[0] != 1) { + # Find out which nodes are really mine only when not sharedtftp and not disjoint mode. + # For other case, all passing node range are required to be handled. + my %iphash = (); + # flag the IPs or names in iphash + foreach (@hostinfo) { $iphash{$_} = 1; } + + # Get managed node list under current server + # The node will be under under 'site.master' if no 'noderes.servicenode' is defined + my $sn_hash = xCAT::ServiceNodeUtils->getSNformattedhash(\@rnodes, "xcat", "MN"); + #my %managed = (); + my $req2manage = 0; + foreach (keys %$sn_hash) { + if (exists($iphash{$_})) { + #my $cur_xmaster = $_; + #foreach (@{ $sn_hash->{$cur_xmaster} }) { $managed{$_} = 1; } + $req2manage = 1; + last; + } + } + if ($req2manage == 0) { + xCAT::MsgUtils->trace(0, "d", "xnba: No nodes are required to be managed on this server"); + return; + } + } + my $rsp; + $rsp->{errorcode}->[0] = 1; + $rsp->{error}->[0] = "Failed to generate xnba configurations for some node(s) on $::myxcatname. Check xCAT log file for more details.\n"; + $::XNBA_callback->($rsp); return; } - if (ref($::XNBA_request->{arg})) { - @args = @{ $::XNBA_request->{arg} }; - } else { - @args = ($::XNBA_request->{arg}); - } - #now run the begin part of the prescripts - unless ($args[0] eq 'stat') { # or $args[0] eq 'enact') { + unless ($args[0] eq '') { # or $args[0] eq 'enact') { $errored = 0; if ($::XNBA_request->{'_disparatetftp'}->[0]) { #the call is distrubuted to the service node already, so only need to handles my own children xCAT::MsgUtils->trace($verbose_on_off, "d", "xnba: the call is distrubuted to the service node already, so only need to handles my own children"); @@ -560,7 +588,7 @@ sub process_request { xCAT::MsgUtils->trace($verbose_on_off, "d", "xnba: nodeset did not distribute to the service node"); xCAT::MsgUtils->trace($verbose_on_off, "d", "xnba: issue runbeginpre request"); $sub_req->({ command => ['runbeginpre'], - node => \@rnodes, + node => \@nodes, arg => [ $args[0] ] }, \&pass_along); } if ($errored) { @@ -592,7 +620,7 @@ sub process_request { if (!$inittime) { $inittime = 0; } my %bphash; - unless ($args[0] eq 'stat') { # or $args[0] eq 'enact') { + unless ($args[0] eq '') { # or $args[0] eq 'enact') { $errored = 0; xCAT::MsgUtils->trace($verbose_on_off, "d", "xnba: issue setdestiny request"); $sub_req->({ command => ['setdestiny'], @@ -607,6 +635,7 @@ sub process_request { } } + xCAT::MsgUtils->trace($verbose_on_off, "d", "xnba: starting to handle configuration..."); #Time to actually configure the nodes, first extract database data with the scalable calls my $chaintab = xCAT::Table->new('chain'); my $noderestab = xCAT::Table->new('noderes'); #in order to detect per-node tftp directories @@ -634,10 +663,7 @@ sub process_request { mkpath($tftpdir . "/xcat/xnba/nodes/"); my %response; $response{node}->[0]->{name}->[0] = $_; - if ($args[0] eq 'stat') { - $response{node}->[0]->{data}->[0] = getstate($_, $tftpdir); - $::XNBA_callback->(\%response); - } elsif ($args[0]) { #If anything else, send it on to the destiny plugin, then setstate + if ($args[0]) { # Send it on to the destiny plugin, then setstate my $rc; my $errstr; my $ent = $typehash->{$_}->[0]; @@ -662,43 +688,36 @@ sub process_request { } } } + xCAT::MsgUtils->trace($verbose_on_off, "d", "xnba: Finish to handle configurations"); # for offline operation, remove the dhcp entries if ($args[0] eq 'offline') { $sub_req->({ command => ['makedhcp'], arg => ['-d'], node => \@nodes }, $::XNBA_callback); } - #dhcp stuff -- inittime is set when xcatd on sn is started - unless (($args[0] eq 'stat') || ($inittime) || ($args[0] eq 'offline')) { + unless (($inittime) || ($args[0] eq 'offline')) { my $do_dhcpsetup = 1; - - #my $sitetab = xCAT::Table->new('site'); - #if ($sitetab) { - #(my $ref) = $sitetab->getAttribs({key => 'dhcpsetup'}, 'value'); my @entries = xCAT::TableUtils->get_site_attribute("dhcpsetup"); my $t_entry = $entries[0]; if (defined($t_entry)) { if ($t_entry =~ /0|n|N/) { $do_dhcpsetup = 0; } } - - #} - if ($do_dhcpsetup) { - if ($::XNBA_request->{'_disparatetftp'}->[0]) { #reading hint from preprocess_command - xCAT::MsgUtils->trace($verbose_on_off, "d", "xnba: issue makedhcp request"); - $sub_req->({ command => ['makedhcp'], arg => ['-l'], - node => \@nodes }, $::XNBA_callback); - } else { - xCAT::MsgUtils->trace($verbose_on_off, "d", "xnba: issue makedhcp request"); - $sub_req->({ command => ['makedhcp'], - node => \@nodes }, $::XNBA_callback); - } + my @parameter; + push @parameter, '-l' if ($::request->{'_disparatetftp'}->[0]); + xCAT::MsgUtils->trace($verbose_on_off, "d", "xnba: issue makedhcp request"); + + $sub_req->({ command => ['makedhcp'], + arg => \@parameter, + node => \@nodes }, $::XNBA_callback); + } else { + xCAT::MsgUtils->trace($verbose_on_off, "d", "xnba: dhcpsetup=$do_dhcpsetup"); } } #now run the end part of the prescripts - unless ($args[0] eq 'stat') { # or $args[0] eq 'enact') + unless ($args[0] eq '') { # or $args[0] eq 'enact') $errored = 0; if ($::XNBA_request->{'_disparatetftp'}->[0]) { #the call is distrubuted to the service node already, so only need to handle my own children xCAT::MsgUtils->trace($verbose_on_off, "d", "xnba: issue runendpre request"); @@ -708,7 +727,7 @@ sub process_request { } else { #nodeset did not distribute to the service node, here we need to let runednpre to distribute the nodes to their masters xCAT::MsgUtils->trace($verbose_on_off, "d", "xnba: issue runendpre request"); $sub_req->({ command => ['runendpre'], - node => \@rnodes, + node => \@nodes, arg => [ $args[0] ] }, \&pass_along); } if ($errored) { @@ -719,6 +738,15 @@ sub process_request { } } + # Return error codes if there are failed nodes + if (%failurenodes) { + my $rsp; + $rsp->{errorcode}->[0] = 1; + $rsp->{error}->[0] = "Failed to generate xnba configurations for some node(s) on $::myxcatname. Check xCAT log file for more details.\n"; + $::XNBA_callback->($rsp); + return; + } + } From 31ba541657272b12332ae0c34f0ef0f0888f3661 Mon Sep 17 00:00:00 2001 From: Bin Xu Date: Thu, 27 Jul 2017 15:55:30 +0800 Subject: [PATCH 5/7] Forwarding to MN if the request is accepted by SN --- perl-xCAT/xCAT/Scope.pm | 58 +++++++++++++++++------ xCAT-server/lib/xcat/plugins/grub2.pm | 11 +++-- xCAT-server/lib/xcat/plugins/petitboot.pm | 12 +++-- xCAT-server/lib/xcat/plugins/xnba.pm | 11 +++-- 4 files changed, 65 insertions(+), 27 deletions(-) diff --git a/perl-xCAT/xCAT/Scope.pm b/perl-xCAT/xCAT/Scope.pm index e58d1a279..103e1b65b 100644 --- a/perl-xCAT/xCAT/Scope.pm +++ b/perl-xCAT/xCAT/Scope.pm @@ -1,8 +1,8 @@ package xCAT::Scope; -#use Data::Dumper; use xCAT::Utils; use xCAT::Table; +use xCAT::TableUtils; use xCAT::ServiceNodeUtils qw(getSNList); @@ -148,22 +148,31 @@ sub get_broadcast_scope_with_parallel { if ($req->{_xcatpreprocessed}->[0] == 1) { return [$req]; } my $snlist = shift; + my @reqs = (); + $req->{_xcatpreprocessed}->[0] = 1; + my $isMN = xCAT::Utils->isMN(); #Handle the one for current management/service node - my $reqs = get_parallel_scope($req); + if ( $isMN ) { + $reqs = get_parallel_scope($req); + } else { + # get site.master and broadcast to it as MN will not be in SN list or defined in noderes.servicenode. + my @entries = xCAT::TableUtils->get_site_attribute("master"); + my $master = $entries[0]; + my $reqcopy = {%$req}; + $reqcopy->{'_xcatdest'} = $master; + $reqs = get_parallel_scope($reqcopy); + } my @requests = @$reqs; #Broadcast the request to other management/service nodes foreach (@$snlist) { my $xcatdest = $_; - if (xCAT::NetworkUtils->thishostisnot($xcatdest)) { - my $reqcopy = {%$req}; - $reqcopy->{'_xcatdest'} = $xcatdest; - $reqcopy->{_xcatpreprocessed}->[0] = 1; + my $reqcopy = {%$req}; + $reqcopy->{'_xcatdest'} = $xcatdest; - $reqs = get_parallel_scope($reqcopy); - foreach (@$reqs) { - push @requests, {%$_}; - } + $reqs = get_parallel_scope($reqcopy); + foreach (@$reqs) { + push @requests, {%$_}; } } return \@requests; @@ -197,12 +206,22 @@ sub get_broadcast_disjoint_scope_with_parallel { my $sn_hash = shift; my @reqs = (); + $req->{_xcatpreprocessed}->[0] = 1; + my $isMN = xCAT::Utils->isMN(); #Handle the one for current management/service node - if ( xCAT::Utils->isMN() ) { - $reqs = get_parallel_scope($req); + if ( $isMN ) { + $reqs = get_parallel_scope($req); + } else { + # get site.master and broadcast to it as MN will not be in SN list or defined in noderes.servicenode. + my @entries = xCAT::TableUtils->get_site_attribute("master"); + my $master = $entries[0]; + my $reqcopy = {%$req}; + $reqcopy->{'_xcatdest'} = $master; + $reqs = get_parallel_scope($reqcopy); } my @requests = @$reqs; + my $handled4me = 0; #Broadcast the request to other management/service nodes foreach (keys %$sn_hash) { my $xcatdest = $_; @@ -210,15 +229,26 @@ sub get_broadcast_disjoint_scope_with_parallel { my $reqcopy = {%$req}; $reqcopy->{'_xcatdest'} = $xcatdest; $reqcopy->{'node'} = $sn_hash->{$xcatdest}; - $reqcopy->{_xcatpreprocessed}->[0] = 1; $reqs = get_parallel_scope($reqcopy); foreach (@$reqs) { push @requests, {%$_}; } + } elsif ($isMN == 0) { + # avoid handle myself multiple times when different IP address used in `noderes.servicenode`. + next if $handled4me; + my $reqcopy = {%$req}; + $reqcopy->{'_xcatdest'} = $xcatdest; + $reqcopy->{'node'} = $sn_hash->{$xcatdest}; + + $reqs = get_parallel_scope($reqcopy); + foreach (@$reqs) { + push @requests, {%$_}; + } + $handled4me = 1; } } - #print Dumper(\@requests); + return \@requests; } diff --git a/xCAT-server/lib/xcat/plugins/grub2.pm b/xCAT-server/lib/xcat/plugins/grub2.pm index 4820f4307..a09612745 100644 --- a/xCAT-server/lib/xcat/plugins/grub2.pm +++ b/xCAT-server/lib/xcat/plugins/grub2.pm @@ -573,7 +573,7 @@ sub process_request { my $errormsg = $ipret->{'error'}; my $nodeip = $ipret->{'ip'}; if ($errormsg) {# Add the node to failure set - xCAT::MsgUtils->trace(0, "E", "grub2: IP address of $_ is $nodeip. $errormsg"); + xCAT::MsgUtils->trace(0, "E", "grub2: Defined IP address of $_ is $nodeip. $errormsg"); unless ($nodeip) { $failurenodes{$_} = 1; } @@ -606,7 +606,10 @@ sub process_request { unless (@nodes) { xCAT::MsgUtils->message("S", "xCAT: grub2 netboot: no valid nodes. Stop the operation on this server."); - # It must be an error if my managed nodes are not handled. + # We need special hanlding to see if the plugin needs report error. + # - For MN, it is designed to handle all nodes, any error is required to be reqport. (All nodes are handled on MN if sharedtftp=1) + # - For SN, if disjointdhcps=1 AND sharedtftp=0, all nodes in the request are the nodes managed by this SN, so we need report error + # if disjointdhcps=1 AND sharedtftp=0, report error only if there are nodes are managed by me. if (xCAT::Utils->isMN() != 1 && $request->{'_disparatetftp'}->[0] && $request->{'_disjointmode'}->[0] != 1) { # Find out which nodes are really mine only when not sharedtftp and not disjoint mode. # For other case, all passing node range are required to be handled. @@ -634,7 +637,7 @@ sub process_request { } my $rsp; $rsp->{errorcode}->[0] = 1; - $rsp->{error}->[0] = "Failed to generate grub2 configurations for some node(s) on $::myxcatname. Check xCAT log file for more details.\n"; + $rsp->{error}->[0] = "Failed to generate grub2 configurations for some node(s) on $::myxcatname. Check xCAT log file for more details."; $callback->($rsp); return; } @@ -878,7 +881,7 @@ sub process_request { if (%failurenodes) { my $rsp; $rsp->{errorcode}->[0] = 1; - $rsp->{error}->[0] = "Failed to generate grub2 configurations for some node(s) on $::myxcatname. Check xCAT log file for more details.\n"; + $rsp->{error}->[0] = "Failed to generate grub2 configurations for some node(s) on $::myxcatname. Check xCAT log file for more details."; $callback->($rsp); return; } diff --git a/xCAT-server/lib/xcat/plugins/petitboot.pm b/xCAT-server/lib/xcat/plugins/petitboot.pm index 89c02fd3b..58d2bd794 100644 --- a/xCAT-server/lib/xcat/plugins/petitboot.pm +++ b/xCAT-server/lib/xcat/plugins/petitboot.pm @@ -1,7 +1,6 @@ # IBM(c) 2014 EPL license http://www.eclipse.org/legal/epl-v10.html package xCAT_plugin::petitboot; -#use Data::Dumper; use File::Path; use Getopt::Long; use xCAT::Table; @@ -464,7 +463,7 @@ sub process_request { my $errormsg = $ipret->{'error'}; my $nodeip = $ipret->{'ip'}; if ($errormsg) {# Add the node to failure set - xCAT::MsgUtils->trace(0, "E", "petitboot: IP address of $_ is $nodeip. $errormsg"); + xCAT::MsgUtils->trace(0, "E", "petitboot: Defined IP address of $_ is $nodeip. $errormsg"); unless ($nodeip) { $failurenodes{$_} = 1; } @@ -497,7 +496,10 @@ sub process_request { unless (@nodes) { xCAT::MsgUtils->message("S", "xCAT: petitboot netboot: no valid nodes. Stop the operation on this server."); - # It must be an error if my managed nodes are not handled. + # We need special hanlding to see if the plugin needs report error. + # - For MN, it is designed to handle all nodes, any error is required to be reqport. (All nodes are handled on MN if sharedtftp=1) + # - For SN, if disjointdhcps=1 AND sharedtftp=0, all nodes in the request are the nodes managed by this SN, so we need report error + # if disjointdhcps=1 AND sharedtftp=0, report error only if there are nodes are managed by me. if (xCAT::Utils->isMN() != 1 && $request->{'_disparatetftp'}->[0] && $request->{'_disjointmode'}->[0] != 1) { # Find out which nodes are really mine only when not sharedtftp and not disjoint mode. # For other case, all passing node range are required to be handled. @@ -525,7 +527,7 @@ sub process_request { } my $rsp; $rsp->{errorcode}->[0] = 1; - $rsp->{error}->[0] = "Failed to generate petitboot configurations for some node(s) on $::myxcatname. Check xCAT log file for more details.\n"; + $rsp->{error}->[0] = "Failed to generate petitboot configurations for some node(s) on $::myxcatname. Check xCAT log file for more details."; $callback->($rsp); return; } @@ -696,7 +698,7 @@ sub process_request { if (%failurenodes) { my $rsp; $rsp->{errorcode}->[0] = 1; - $rsp->{error}->[0] = "Failed to generate petitboot configurations for some node(s) on $::myxcatname. Check xCAT log file for more details.\n"; + $rsp->{error}->[0] = "Failed to generate petitboot configurations for some node(s) on $::myxcatname. Check xCAT log file for more details."; $callback->($rsp); return; } diff --git a/xCAT-server/lib/xcat/plugins/xnba.pm b/xCAT-server/lib/xcat/plugins/xnba.pm index da8d8d467..d18b3d004 100644 --- a/xCAT-server/lib/xcat/plugins/xnba.pm +++ b/xCAT-server/lib/xcat/plugins/xnba.pm @@ -509,7 +509,7 @@ sub process_request { my $errormsg = $ipret->{'error'}; my $nodeip = $ipret->{'ip'}; if ($errormsg) {# Add the node to failure set - xCAT::MsgUtils->trace(0, "E", "xnba: IP address of $_ is $nodeip. $errormsg"); + xCAT::MsgUtils->trace(0, "E", "xnba: Defined IP address of $_ is $nodeip. $errormsg"); unless ($nodeip) { $failurenodes{$_} = 1; } @@ -542,7 +542,10 @@ sub process_request { unless (@nodes) { xCAT::MsgUtils->message("S", "xCAT: xnba netboot: no valid nodes. Stop the operation on this server."); - # It must be an error if my managed nodes are not handled. + # We need special hanlding to see if the plugin needs report error. + # - For MN, it is designed to handle all nodes, any error is required to be reqport. (All nodes are handled on MN if sharedtftp=1) + # - For SN, if disjointdhcps=1 AND sharedtftp=0, all nodes in the request are the nodes managed by this SN, so we need report error + # if disjointdhcps=1 AND sharedtftp=0, report error only if there are nodes are managed by me. if (xCAT::Utils->isMN() != 1 && $::XNBA_request->{'_disparatetftp'}->[0] && $::XNBA_request->{'_disjointmode'}->[0] != 1) { # Find out which nodes are really mine only when not sharedtftp and not disjoint mode. # For other case, all passing node range are required to be handled. @@ -570,7 +573,7 @@ sub process_request { } my $rsp; $rsp->{errorcode}->[0] = 1; - $rsp->{error}->[0] = "Failed to generate xnba configurations for some node(s) on $::myxcatname. Check xCAT log file for more details.\n"; + $rsp->{error}->[0] = "Failed to generate xnba configurations for some node(s) on $::myxcatname. Check xCAT log file for more details."; $::XNBA_callback->($rsp); return; } @@ -742,7 +745,7 @@ sub process_request { if (%failurenodes) { my $rsp; $rsp->{errorcode}->[0] = 1; - $rsp->{error}->[0] = "Failed to generate xnba configurations for some node(s) on $::myxcatname. Check xCAT log file for more details.\n"; + $rsp->{error}->[0] = "Failed to generate xnba configurations for some node(s) on $::myxcatname. Check xCAT log file for more details."; $::XNBA_callback->($rsp); return; } From 770d947c949d99f8abacd8e9fbdab4b14f9e6250 Mon Sep 17 00:00:00 2001 From: Bin Xu Date: Fri, 28 Jul 2017 16:36:15 +0800 Subject: [PATCH 6/7] Using networks.dhcpserver as one accept whole noderange for nodeset. --- perl-xCAT/xCAT/Scope.pm | 101 ++++++++++++---------- xCAT-server/lib/xcat/plugins/grub2.pm | 11 ++- xCAT-server/lib/xcat/plugins/petitboot.pm | 11 ++- xCAT-server/lib/xcat/plugins/xnba.pm | 11 ++- 4 files changed, 85 insertions(+), 49 deletions(-) diff --git a/perl-xCAT/xCAT/Scope.pm b/perl-xCAT/xCAT/Scope.pm index 103e1b65b..b35388fe3 100644 --- a/perl-xCAT/xCAT/Scope.pm +++ b/perl-xCAT/xCAT/Scope.pm @@ -146,33 +146,35 @@ sub get_broadcast_scope_with_parallel { } #Exit if the packet has been preprocessed in its history if ($req->{_xcatpreprocessed}->[0] == 1) { return [$req]; } + $req->{_xcatpreprocessed}->[0] = 1; my $snlist = shift; - my @reqs = (); - $req->{_xcatpreprocessed}->[0] = 1; - my $isMN = xCAT::Utils->isMN(); - #Handle the one for current management/service node - if ( $isMN ) { - $reqs = get_parallel_scope($req); - } else { - # get site.master and broadcast to it as MN will not be in SN list or defined in noderes.servicenode. + + my $reqs = get_parallel_scope($req); + + my @requests = (); # The request array will be return. + push @requests, @$reqs; + + # get site.master from DB and dispatch to it as MN will not be in SN list. + if ( xCAT::Utils->isServiceNode() ) { my @entries = xCAT::TableUtils->get_site_attribute("master"); my $master = $entries[0]; - my $reqcopy = {%$req}; - $reqcopy->{'_xcatdest'} = $master; - $reqs = get_parallel_scope($reqcopy); + foreach (@$reqs) { + my $reqcopy = {%$_}; + $reqcopy->{'_xcatdest'} = $master; + push @requests, $reqcopy; + } } - my @requests = @$reqs; - #Broadcast the request to other management/service nodes + #Broadcast the request to all service nodes foreach (@$snlist) { my $xcatdest = $_; - my $reqcopy = {%$req}; - $reqcopy->{'_xcatdest'} = $xcatdest; + next unless (xCAT::NetworkUtils->thishostisnot($xcatdest)); - $reqs = get_parallel_scope($reqcopy); foreach (@$reqs) { - push @requests, {%$_}; + my $reqcopy = {%$_}; + $reqcopy->{'_xcatdest'} = $xcatdest; + push @requests, $reqcopy; } } return \@requests; @@ -182,12 +184,13 @@ sub get_broadcast_scope_with_parallel { =head3 get_broadcast_disjoint_scope_with_parallel - Convert a request object to an array of multiple requests according to the - splitted node range. (Work under disjoint mode) + Convert a request object to an array of multiple request objects according to the + service node management scope. (Work under disjoint mode) Arguments: Reference of request SN hash: Hash of target service nodes => Managed CNs + Special servers: Array of servers, those servers are required to handle whole noderange. Returns: An array of requests Error: none @@ -203,48 +206,54 @@ sub get_broadcast_disjoint_scope_with_parallel { } #Exit if the packet has been preprocessed in its history if ($req->{_xcatpreprocessed}->[0] == 1) { return [$req]; } + $req->{_xcatpreprocessed}->[0] = 1; my $sn_hash = shift; - my @reqs = (); - $req->{_xcatpreprocessed}->[0] = 1; - my $isMN = xCAT::Utils->isMN(); - #Handle the one for current management/service node - if ( $isMN ) { - $reqs = get_parallel_scope($req); - } else { - # get site.master and broadcast to it as MN will not be in SN list or defined in noderes.servicenode. - my @entries = xCAT::TableUtils->get_site_attribute("master"); - my $master = $entries[0]; - my $reqcopy = {%$req}; - $reqcopy->{'_xcatdest'} = $master; - $reqs = get_parallel_scope($reqcopy); - } - my @requests = @$reqs; + my $extras = shift; - my $handled4me = 0; - #Broadcast the request to other management/service nodes + my @requests = (); # The request array will be return. + my $reqs = get_parallel_scope($req); + + my $handled4me = 0; # indicate myself is already handled. + my %prehandledhash = ();# the servers which is already handled. + foreach (@$extras) { + my $xcatdest = $_; + if (xCAT::NetworkUtils->thishostisnot($xcatdest)) { + # TODO, To avoid sending request to a multi-home server many times. + foreach (@$reqs) { + my $reqcopy = {%$_}; + $reqcopy->{'_xcatdest'} = $xcatdest; + push @requests, $reqcopy; + } + $prehandledhash{$xcatdest} = 1; + } elsif ($handled4me == 0) { + push @requests, @$reqs; + $handled4me = 1; + } + } + + #Broadcast the request to all available service nodes foreach (keys %$sn_hash) { my $xcatdest = $_; + # to check if the SN already handled + next if (exists($prehandledhash{$xcatdest})); + if (xCAT::NetworkUtils->thishostisnot($xcatdest)) { my $reqcopy = {%$req}; $reqcopy->{'_xcatdest'} = $xcatdest; $reqcopy->{'node'} = $sn_hash->{$xcatdest}; $reqs = get_parallel_scope($reqcopy); - foreach (@$reqs) { - push @requests, {%$_}; - } - } elsif ($isMN == 0) { - # avoid handle myself multiple times when different IP address used in `noderes.servicenode`. - next if $handled4me; + push @requests, @$reqs; + #foreach (@$reqs) { + # push @requests, {%$_}; + #} + } elsif ($handled4me == 0) { my $reqcopy = {%$req}; - $reqcopy->{'_xcatdest'} = $xcatdest; $reqcopy->{'node'} = $sn_hash->{$xcatdest}; $reqs = get_parallel_scope($reqcopy); - foreach (@$reqs) { - push @requests, {%$_}; - } + push @requests, @$reqs; $handled4me = 1; } } diff --git a/xCAT-server/lib/xcat/plugins/grub2.pm b/xCAT-server/lib/xcat/plugins/grub2.pm index a09612745..563595b72 100644 --- a/xCAT-server/lib/xcat/plugins/grub2.pm +++ b/xCAT-server/lib/xcat/plugins/grub2.pm @@ -499,7 +499,16 @@ sub preprocess_request { } my $sn_hash = xCAT::ServiceNodeUtils->getSNformattedhash(\@CN, "xcat", "MN"); - return xCAT::Scope->get_broadcast_disjoint_scope_with_parallel($req, $sn_hash); + my @dhcpsvrs = (); + my $ntab = xCAT::Table->new('networks'); + if ($ntab) { + foreach (@{ $ntab->getAllEntries() }) { + next unless ($_->{dynamicrange}); + # if dynamicrange specified but dhcpserver was not - issue error message + push @dhcpsvrs, $_->{dhcpserver} if ($_->{dhcpserver}) + } + } + return xCAT::Scope->get_broadcast_disjoint_scope_with_parallel($req, $sn_hash, \@dhcpsvrs); } } # Do not dispatch to service nodes if non-sharedtftp or the node range contains only SNs. diff --git a/xCAT-server/lib/xcat/plugins/petitboot.pm b/xCAT-server/lib/xcat/plugins/petitboot.pm index 58d2bd794..46b471f8f 100644 --- a/xCAT-server/lib/xcat/plugins/petitboot.pm +++ b/xCAT-server/lib/xcat/plugins/petitboot.pm @@ -385,7 +385,16 @@ sub preprocess_request { } my $sn_hash = xCAT::ServiceNodeUtils->getSNformattedhash(\@CN, "xcat", "MN"); - return xCAT::Scope->get_broadcast_disjoint_scope_with_parallel($req, $sn_hash); + my @dhcpsvrs = (); + my $ntab = xCAT::Table->new('networks'); + if ($ntab) { + foreach (@{ $ntab->getAllEntries() }) { + next unless ($_->{dynamicrange}); + # if dynamicrange specified but dhcpserver was not - issue error message + push @dhcpsvrs, $_->{dhcpserver} if ($_->{dhcpserver}) + } + } + return xCAT::Scope->get_broadcast_disjoint_scope_with_parallel($req, $sn_hash, \@dhcpsvrs); } } # Do not dispatch to service nodes if non-sharedtftp or the node range contains only SNs. diff --git a/xCAT-server/lib/xcat/plugins/xnba.pm b/xCAT-server/lib/xcat/plugins/xnba.pm index d18b3d004..834434a98 100644 --- a/xCAT-server/lib/xcat/plugins/xnba.pm +++ b/xCAT-server/lib/xcat/plugins/xnba.pm @@ -437,7 +437,16 @@ sub preprocess_request { } my $sn_hash = xCAT::ServiceNodeUtils->getSNformattedhash(\@CN, "xcat", "MN"); - return xCAT::Scope->get_broadcast_disjoint_scope_with_parallel($req, $sn_hash); + my @dhcpsvrs = (); + my $ntab = xCAT::Table->new('networks'); + if ($ntab) { + foreach (@{ $ntab->getAllEntries() }) { + next unless ($_->{dynamicrange}); + # if dynamicrange specified but dhcpserver was not - issue error message + push @dhcpsvrs, $_->{dhcpserver} if ($_->{dhcpserver}) + } + } + return xCAT::Scope->get_broadcast_disjoint_scope_with_parallel($req, $sn_hash, \@dhcpsvrs); } } # Do not dispatch to service nodes if non-sharedtftp or the node range contains only SNs. From 0d85cd441be3d7f42a8266ecd0b4e6cb210a9519 Mon Sep 17 00:00:00 2001 From: Bin Xu Date: Wed, 2 Aug 2017 14:39:28 +0800 Subject: [PATCH 7/7] 1, Make the function header and comments more clear --- perl-xCAT/xCAT/Scope.pm | 15 ++++++++------- xCAT-server/lib/xcat/plugins/grub2.pm | 16 +++++----------- xCAT-server/lib/xcat/plugins/petitboot.pm | 16 +++++----------- xCAT-server/lib/xcat/plugins/xnba.pm | 16 +++++----------- 4 files changed, 23 insertions(+), 40 deletions(-) diff --git a/perl-xCAT/xCAT/Scope.pm b/perl-xCAT/xCAT/Scope.pm index b35388fe3..39bb3da44 100644 --- a/perl-xCAT/xCAT/Scope.pm +++ b/perl-xCAT/xCAT/Scope.pm @@ -126,7 +126,8 @@ sub get_parallel_scope { =head3 get_broadcast_scope_with_parallel Convert a request object to an array of multiple requests according to the - splitted node range. + splitted node range. Also it replicates the requests to all required service + nodes or management node. Arguments: Reference of request @@ -155,7 +156,8 @@ sub get_broadcast_scope_with_parallel { my @requests = (); # The request array will be return. push @requests, @$reqs; - # get site.master from DB and dispatch to it as MN will not be in SN list. + # when this method is called on service node, it is required to broadcast to MN too. + # get site.master from DB in order to dispatch to MN ( MN will not be added in servicenode table) if ( xCAT::Utils->isServiceNode() ) { my @entries = xCAT::TableUtils->get_site_attribute("master"); my $master = $entries[0]; @@ -184,8 +186,10 @@ sub get_broadcast_scope_with_parallel { =head3 get_broadcast_disjoint_scope_with_parallel - Convert a request object to an array of multiple request objects according to the - service node management scope. (Work under disjoint mode) + Convert a request object to an array of multiple requests according to the + splitted node range. Also it replicates the requests to all required service + nodes or management node, but the request to a service node will only contains + the node range it manages. Arguments: Reference of request @@ -245,9 +249,6 @@ sub get_broadcast_disjoint_scope_with_parallel { $reqs = get_parallel_scope($reqcopy); push @requests, @$reqs; - #foreach (@$reqs) { - # push @requests, {%$_}; - #} } elsif ($handled4me == 0) { my $reqcopy = {%$req}; $reqcopy->{'node'} = $sn_hash->{$xcatdest}; diff --git a/xCAT-server/lib/xcat/plugins/grub2.pm b/xCAT-server/lib/xcat/plugins/grub2.pm index 563595b72..03482eeb4 100644 --- a/xCAT-server/lib/xcat/plugins/grub2.pm +++ b/xCAT-server/lib/xcat/plugins/grub2.pm @@ -1,6 +1,6 @@ # IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html package xCAT_plugin::grub2; -#use Data::Dumper; + use Sys::Syslog; use xCAT::Scope; use xCAT::Utils; @@ -611,17 +611,13 @@ sub process_request { my $str_node = join(" ", @nodes); xCAT::MsgUtils->trace($verbose_on_off, "d", "grub2: nodes are $str_node") if ($str_node); - # return directly if no nodes in the same network + # Return directly if no nodes in the same network, need to report error on console if its managed nodes are not handled. unless (@nodes) { xCAT::MsgUtils->message("S", "xCAT: grub2 netboot: no valid nodes. Stop the operation on this server."); - # We need special hanlding to see if the plugin needs report error. - # - For MN, it is designed to handle all nodes, any error is required to be reqport. (All nodes are handled on MN if sharedtftp=1) - # - For SN, if disjointdhcps=1 AND sharedtftp=0, all nodes in the request are the nodes managed by this SN, so we need report error - # if disjointdhcps=1 AND sharedtftp=0, report error only if there are nodes are managed by me. - if (xCAT::Utils->isMN() != 1 && $request->{'_disparatetftp'}->[0] && $request->{'_disjointmode'}->[0] != 1) { + # If non-shared tftproot and non disjoint mode, need to figure out if no nodes here is a normal case. + if ($request->{'_disparatetftp'}->[0] && $request->{'_disjointmode'}->[0] != 1) { # Find out which nodes are really mine only when not sharedtftp and not disjoint mode. - # For other case, all passing node range are required to be handled. my %iphash = (); # flag the IPs or names in iphash foreach (@hostinfo) { $iphash{$_} = 1; } @@ -629,16 +625,14 @@ sub process_request { # Get managed node list under current server # The node will be under under 'site.master' if no 'noderes.servicenode' is defined my $sn_hash = xCAT::ServiceNodeUtils->getSNformattedhash(\@rnodes, "xcat", "MN"); - #my %managed = (); my $req2manage = 0; foreach (keys %$sn_hash) { if (exists($iphash{$_})) { - #my $cur_xmaster = $_; - #foreach (@{ $sn_hash->{$cur_xmaster} }) { $managed{$_} = 1; } $req2manage = 1; last; } } + # Okay, now report error as no nodes are handled. if ($req2manage == 0) { xCAT::MsgUtils->trace(0, "d", "grub2: No nodes are required to be managed on this server"); return; diff --git a/xCAT-server/lib/xcat/plugins/petitboot.pm b/xCAT-server/lib/xcat/plugins/petitboot.pm index 46b471f8f..af3320ae2 100644 --- a/xCAT-server/lib/xcat/plugins/petitboot.pm +++ b/xCAT-server/lib/xcat/plugins/petitboot.pm @@ -501,17 +501,13 @@ sub process_request { my $str_node = join(" ", @nodes); xCAT::MsgUtils->trace($verbose_on_off, "d", "petitboot: nodes are $str_node") if ($str_node); - # Return directly if no nodes in the same network + # Return directly if no nodes in the same network, need to report error on console if its managed nodes are not handled. unless (@nodes) { xCAT::MsgUtils->message("S", "xCAT: petitboot netboot: no valid nodes. Stop the operation on this server."); - # We need special hanlding to see if the plugin needs report error. - # - For MN, it is designed to handle all nodes, any error is required to be reqport. (All nodes are handled on MN if sharedtftp=1) - # - For SN, if disjointdhcps=1 AND sharedtftp=0, all nodes in the request are the nodes managed by this SN, so we need report error - # if disjointdhcps=1 AND sharedtftp=0, report error only if there are nodes are managed by me. - if (xCAT::Utils->isMN() != 1 && $request->{'_disparatetftp'}->[0] && $request->{'_disjointmode'}->[0] != 1) { + # If non-shared tftproot and non disjoint mode, need to figure out if no nodes here is a normal case. + if ($request->{'_disparatetftp'}->[0] && $request->{'_disjointmode'}->[0] != 1) { # Find out which nodes are really mine only when not sharedtftp and not disjoint mode. - # For other case, all passing node range are required to be handled. my %iphash = (); # flag the IPs or names in iphash foreach (@hostinfo) { $iphash{$_} = 1; } @@ -519,21 +515,19 @@ sub process_request { # Get managed node list under current server # The node will be under under 'site.master' if no 'noderes.servicenode' is defined my $sn_hash = xCAT::ServiceNodeUtils->getSNformattedhash(\@rnodes, "xcat", "MN"); - #my %managed = (); my $req2manage = 0; foreach (keys %$sn_hash) { if (exists($iphash{$_})) { - #my $cur_xmaster = $_; - #foreach (@{ $sn_hash->{$cur_xmaster} }) { $managed{$_} = 1; } $req2manage = 1; last; } } if ($req2manage == 0) { - xCAT::MsgUtils->trace(0, "d", "petitboot: No nodes are required to be managed on this server"); + #No nodes are required to be handled, quit without error. return; } } + # Okay, now report error as no nodes are handled. my $rsp; $rsp->{errorcode}->[0] = 1; $rsp->{error}->[0] = "Failed to generate petitboot configurations for some node(s) on $::myxcatname. Check xCAT log file for more details."; diff --git a/xCAT-server/lib/xcat/plugins/xnba.pm b/xCAT-server/lib/xcat/plugins/xnba.pm index 834434a98..7250f1b6c 100644 --- a/xCAT-server/lib/xcat/plugins/xnba.pm +++ b/xCAT-server/lib/xcat/plugins/xnba.pm @@ -547,17 +547,13 @@ sub process_request { my $str_node = join(" ", @nodes); xCAT::MsgUtils->trace(0, "d", "xnba: nodes are $str_node") if ($str_node); - # return directly if no nodes in the same network + # Return directly if no nodes in the same network, need to report error on console if its managed nodes are not handled. unless (@nodes) { xCAT::MsgUtils->message("S", "xCAT: xnba netboot: no valid nodes. Stop the operation on this server."); - # We need special hanlding to see if the plugin needs report error. - # - For MN, it is designed to handle all nodes, any error is required to be reqport. (All nodes are handled on MN if sharedtftp=1) - # - For SN, if disjointdhcps=1 AND sharedtftp=0, all nodes in the request are the nodes managed by this SN, so we need report error - # if disjointdhcps=1 AND sharedtftp=0, report error only if there are nodes are managed by me. - if (xCAT::Utils->isMN() != 1 && $::XNBA_request->{'_disparatetftp'}->[0] && $::XNBA_request->{'_disjointmode'}->[0] != 1) { + # If non-shared tftproot and non disjoint mode, need to figure out if no nodes here is a normal case. + if ($::XNBA_request->{'_disparatetftp'}->[0] && $::XNBA_request->{'_disjointmode'}->[0] != 1) { # Find out which nodes are really mine only when not sharedtftp and not disjoint mode. - # For other case, all passing node range are required to be handled. my %iphash = (); # flag the IPs or names in iphash foreach (@hostinfo) { $iphash{$_} = 1; } @@ -565,21 +561,19 @@ sub process_request { # Get managed node list under current server # The node will be under under 'site.master' if no 'noderes.servicenode' is defined my $sn_hash = xCAT::ServiceNodeUtils->getSNformattedhash(\@rnodes, "xcat", "MN"); - #my %managed = (); my $req2manage = 0; foreach (keys %$sn_hash) { if (exists($iphash{$_})) { - #my $cur_xmaster = $_; - #foreach (@{ $sn_hash->{$cur_xmaster} }) { $managed{$_} = 1; } $req2manage = 1; last; } } if ($req2manage == 0) { - xCAT::MsgUtils->trace(0, "d", "xnba: No nodes are required to be managed on this server"); + #No nodes are required to be handled, quit without error. return; } } + # Okay, now report error as no nodes are handled. my $rsp; $rsp->{errorcode}->[0] = 1; $rsp->{error}->[0] = "Failed to generate xnba configurations for some node(s) on $::myxcatname. Check xCAT log file for more details.";