From 640ded52ec52c35b01bd54243005f9345ce07f90 Mon Sep 17 00:00:00 2001 From: lissav Date: Tue, 18 Feb 2014 10:14:49 -0500 Subject: [PATCH 1/9] more improvements for zones --- perl-xCAT/xCAT/Zone.pm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/perl-xCAT/xCAT/Zone.pm b/perl-xCAT/xCAT/Zone.pm index bf62b7635..b4cea8bea 100644 --- a/perl-xCAT/xCAT/Zone.pm +++ b/perl-xCAT/xCAT/Zone.pm @@ -279,7 +279,7 @@ sub getzoneinfo $zonehash->{$zonename}->{defaultzone}= $zone->{defaultzone}; # find the defaultzone if ((defined($zone->{defaultzone})) && - (($zone->{defaultzone} =~ "yes") || ($zone->{defaultzone} = "1"))) { + (($zone->{defaultzone} =~ /yes/i) or ($zone->{defaultzone} eq "1"))) { $defaultzone = $zone->{zonename}; } } @@ -324,6 +324,6 @@ sub getzoneinfo } } } - return; + return $zonehash; } 1; From 5500f738245693578f45efd16ab1bc7289706716 Mon Sep 17 00:00:00 2001 From: lissav Date: Tue, 18 Feb 2014 11:08:22 -0500 Subject: [PATCH 2/9] improvements --- perl-xCAT/xCAT/Zone.pm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/perl-xCAT/xCAT/Zone.pm b/perl-xCAT/xCAT/Zone.pm index b4cea8bea..bf62b7635 100644 --- a/perl-xCAT/xCAT/Zone.pm +++ b/perl-xCAT/xCAT/Zone.pm @@ -279,7 +279,7 @@ sub getzoneinfo $zonehash->{$zonename}->{defaultzone}= $zone->{defaultzone}; # find the defaultzone if ((defined($zone->{defaultzone})) && - (($zone->{defaultzone} =~ /yes/i) or ($zone->{defaultzone} eq "1"))) { + (($zone->{defaultzone} =~ "yes") || ($zone->{defaultzone} = "1"))) { $defaultzone = $zone->{zonename}; } } @@ -324,6 +324,6 @@ sub getzoneinfo } } } - return $zonehash; + return; } 1; From 1107b6231032183f8755135a825b6a9b2a09fd5f Mon Sep 17 00:00:00 2001 From: lissav Date: Wed, 19 Feb 2014 05:21:02 -0500 Subject: [PATCH 3/9] add missing -g flag --- xCAT-client/pods/man1/updatenode.1.pod | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/xCAT-client/pods/man1/updatenode.1.pod b/xCAT-client/pods/man1/updatenode.1.pod index 24ad11b11..c698de8ad 100644 --- a/xCAT-client/pods/man1/updatenode.1.pod +++ b/xCAT-client/pods/man1/updatenode.1.pod @@ -327,6 +327,11 @@ For statelite installations to sync files, you should use the read-only option for files/directories listed in litefile table with source location specified in the litetree table. +=item B<-g|--genmypost + +Will generate a new mypostscript file for the +nodes in the noderange, if site precreatemypostscripts is 1 or YES. + =item B<-h|--help> From 8a015d24fd070c34cb94f60b8f83df19e42e6fb6 Mon Sep 17 00:00:00 2001 From: lissav Date: Wed, 19 Feb 2014 05:22:52 -0500 Subject: [PATCH 4/9] add missing -g flag --- xCAT-client/pods/man1/updatenode.1.pod | 2 ++ 1 file changed, 2 insertions(+) diff --git a/xCAT-client/pods/man1/updatenode.1.pod b/xCAT-client/pods/man1/updatenode.1.pod index c698de8ad..441870d53 100644 --- a/xCAT-client/pods/man1/updatenode.1.pod +++ b/xCAT-client/pods/man1/updatenode.1.pod @@ -8,6 +8,8 @@ B B [B<-V>|B<--verbose>] [B<-F>|B<--sync>] [B<-f>|B<--sns B B [B<-k>|B<--security>] [B<-t timeout>] +B B [B<-g>|B<--genmypost>] + B B [B<-V>|B<--verbose>] [B<-t timeout>] [B] B B [B<-V>|B<--verbose>] [B<-f>|B<--snsync>] From 59d675af7bc8d8d9add7fa2ace5293c6ee8ccd7c Mon Sep 17 00:00:00 2001 From: lissav Date: Wed, 19 Feb 2014 07:06:28 -0500 Subject: [PATCH 5/9] add zone table sshbetweennodes attribute --- perl-xCAT/xCAT/Schema.pm | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/perl-xCAT/xCAT/Schema.pm b/perl-xCAT/xCAT/Schema.pm index e588ec9f5..51361629a 100755 --- a/perl-xCAT/xCAT/Schema.pm +++ b/perl-xCAT/xCAT/Schema.pm @@ -1052,7 +1052,8 @@ site => { " Set to NOGROUPS,if you do not wish to enabled any group of compute nodes.\n". " Service Nodes are not affected by this attribute\n". " they are always setup with\n". - " passwordless root access to nodes and other SN.\n\n". + " passwordless root access to nodes and other SN.\n". + " If using the zone table, this attribute in not used.\n". " -----------------\n". "SERVICES ATTRIBUTES\n". " -----------------\n". @@ -1191,12 +1192,13 @@ performance => { }, }, zone => { - cols => [qw(zonename sshkeydir defaultzone comments disable)], + cols => [qw(zonename sshkeydir sshbetweennodes defaultzone comments disable)], keys => [qw(zonename)], table_desc => 'Defines a cluster zone for nodes that share root ssh key access to each other.', descriptions => { zonename => 'The name of the zone.', sshkeydir => 'Directory containing the shared root ssh RSA keys.', + sshbetweennodes => 'Indicates whether passwordless ssh will be setup between the nodes of this zone. Values are yes/1 or no/0. Default is yes. ', defaultzone => 'If nodes are not assigned to any other zone, they will default to this zone. If value is set to yes or 1.', comments => 'Any user-provided notes.', disable => "Set to 'yes' or '1' to comment out this row.", @@ -3083,6 +3085,10 @@ push(@{$defspec{node}->{'attrs'}}, @nodeattrs); tabentry => 'zone.sshkeydir', access_tabentry => 'zone.zonename=attr:zonename', }, + {attr_name => 'sshbetweennodes', + tabentry => 'zone.sshbetweennodes', + access_tabentry => 'zone.zonename=attr:zonename', + }, {attr_name => 'defaultzone', tabentry => 'zone.defaultzone', access_tabentry => 'zone.zonename=attr:zonename', From d80d7a974ff47b83ae5fc06635e66ca5d3090958 Mon Sep 17 00:00:00 2001 From: lissav Date: Wed, 19 Feb 2014 07:14:15 -0500 Subject: [PATCH 6/9] add zone table sshbetweennodes attribute --- perl-xCAT/xCAT/Schema.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/perl-xCAT/xCAT/Schema.pm b/perl-xCAT/xCAT/Schema.pm index 51361629a..6850e50f2 100755 --- a/perl-xCAT/xCAT/Schema.pm +++ b/perl-xCAT/xCAT/Schema.pm @@ -1053,7 +1053,7 @@ site => { " Service Nodes are not affected by this attribute\n". " they are always setup with\n". " passwordless root access to nodes and other SN.\n". - " If using the zone table, this attribute in not used.\n". + " If using the zone table, this attribute in not used.\n\n". " -----------------\n". "SERVICES ATTRIBUTES\n". " -----------------\n". From 00318b28d4cc719eb9a676f9f29391a71edd241e Mon Sep 17 00:00:00 2001 From: lissav Date: Wed, 19 Feb 2014 08:48:14 -0500 Subject: [PATCH 7/9] designchanges --- xCAT-server/lib/xcat/plugins/zone.pm | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/xCAT-server/lib/xcat/plugins/zone.pm b/xCAT-server/lib/xcat/plugins/zone.pm index 19efa20c7..91398d3a8 100644 --- a/xCAT-server/lib/xcat/plugins/zone.pm +++ b/xCAT-server/lib/xcat/plugins/zone.pm @@ -108,6 +108,7 @@ sub process_request 'h|help' => \$options{'help'}, 'k|sshkeypath=s' => \$options{'sshkeypath'}, 'K|genkeys' => \$options{'gensshkeys'}, + 's|sshbetweennodes=s' => \$options{'sshbetweennodes'}, 'v|version' => \$options{'version'}, 'V|Verbose' => \$options{'verbose'}, ) @@ -244,6 +245,7 @@ sub mkzone # Create path to generated ssh keys $keydir .= $request->{zonename}; + # update the zone table $rc=updatezonetable($request, $callback,$options,$keydir); @@ -337,11 +339,11 @@ sub usage my $usagemsg2=""; if ($command eq "mkzone") { $usagemsg1 = " mkzone -h \n mkzone -v \n"; - $usagemsg2 = " mkzone [-V] [--defaultzone] [-k ] [-g] [-f]"; + $usagemsg2 = " mkzone [-V] [--defaultzone] [-k ] [-g] [-f] [-s ]"; } else { if ($command eq "chzone") { $usagemsg1 = " chzone -h \n chzone -v \n"; - $usagemsg2 = " chzone [-V] [--defaultzone] [-k ] [-r ] [-g] "; + $usagemsg2 = " chzone [-V] [--defaultzone] [-k ] [-r ] [-g] [-s ]"; } else { if ($command eq "rmzone") { $usagemsg1 = " rmzone -h \n rmzone -v \n"; @@ -424,6 +426,18 @@ sub updatezonetable my $tab = xCAT::Table->new("zone"); if ($tab) { + # read a record from the zone table, if it is empty then add + # the xcatdefault entry + my @zones = $tab->getAllAttribs('zonename'); + if (!(@zones)) { # table empty + my %xcatdefaultzone; + $xcatdefaultzone{defaultzone} ="yes"; + $xcatdefaultzone{sshbetweennodes} ="yes"; + $xcatdefaultzone{sshkeydir} ="~/.ssh"; + $tab->setAttribs({zonename => "xcatdefault"}, \%xcatdefaultzone); + } + + # now add the users zone my %tb_cols; $tb_cols{sshkeydir} = $keydir; my $zonename=$request->{zonename}; From 82caea177c06d5288f480c9647fe8e3ef42c6cd8 Mon Sep 17 00:00:00 2001 From: lissav Date: Wed, 19 Feb 2014 08:49:43 -0500 Subject: [PATCH 8/9] designchanges --- perl-xCAT/xCAT/Zone.pm | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/perl-xCAT/xCAT/Zone.pm b/perl-xCAT/xCAT/Zone.pm index bf62b7635..6c5c06eb6 100644 --- a/perl-xCAT/xCAT/Zone.pm +++ b/perl-xCAT/xCAT/Zone.pm @@ -199,7 +199,7 @@ sub getdefaultzone foreach my $zone (@zones) { # Look for the defaultzone=yes/1 entry if ((defined($zone->{defaultzone})) && - (($zone->{defaultzone} =~ "yes") || ($zone->{defaultzone} = "1"))) { + (($zone->{defaultzone} =~ "yes") || ($zone->{defaultzone} eq "1"))) { $defaultzone = $zone->{zonename}; } $tab->close(); @@ -255,22 +255,23 @@ sub iszonedefined If the nodes nodelist.zonename attribute is undefined: If there is a defaultzone in the zone table, the node is assigned to that zone If there is no defaultzone in the zone table, the node is assigned to the ~.ssh keydir + $::GETZONEINFO_RC + 0 = good return + 1 = error occured =cut #-------------------------------------------------------------------------------- sub getzoneinfo { my ($class, $callback,$nodes) = @_; - - # make the list into an array -# $nodelist=~ s/\s*//g; # remove blanks -# my @nodes = split ',', $nodelist; + $::GETZONEINFO_RC=0; my $zonehash; my $defaultzone; # read all the zone table my $zonetab = xCAT::Table->new("zone"); + my @zones; if ($zonetab){ - my @zones = $zonetab->getAllAttribs('zonename','sshkeydir','defaultzone'); + @zones = $zonetab->getAllAttribs('zonename','sshkeydir','sshbetweennodes','defaultzone'); $zonetab->close(); if (@zones) { foreach my $zone (@zones) { @@ -279,7 +280,7 @@ sub getzoneinfo $zonehash->{$zonename}->{defaultzone}= $zone->{defaultzone}; # find the defaultzone if ((defined($zone->{defaultzone})) && - (($zone->{defaultzone} =~ "yes") || ($zone->{defaultzone} = "1"))) { + (($zone->{defaultzone} =~ "yes") || ($zone->{defaultzone} eq "1"))) { $defaultzone = $zone->{zonename}; } } @@ -289,6 +290,7 @@ sub getzoneinfo $rsp->{error}->[0] = "Error reading the zone table. "; xCAT::MsgUtils->message("E", $rsp, $callback); + $::GETZONEINFO_RC =1; return; } @@ -314,6 +316,15 @@ sub getzoneinfo $zonename=$nodehash->{$node}->[0]->{zonename}; } if (defined($zonename)) { # zonename explicitly defined in nodelist.zonename + # check to see if defined in the zone table + if (!(grep(/^$zonename$/, @zones))) { + my $rsp = {}; + $rsp->{error}->[0] = + "$node has a zonenane: $zonename that is not define in the zone table. Remove the zonename from the node, or create the zone using mkzone."; + xCAT::MsgUtils->message("E", $rsp, $callback); + $::GETZONEINFO_RC =1; + return; + } push @{$zonehash->{$zonename}->{nodes}},$node; } else { # no explict zonename if (defined ($defaultzone)) { # there is a default zone in the zone table, use it From 9e826d1189ef764c8ae4f03897459378d41bd2f5 Mon Sep 17 00:00:00 2001 From: lissav Date: Wed, 19 Feb 2014 12:50:36 -0500 Subject: [PATCH 9/9] more zone code --- perl-xCAT/xCAT/RemoteShellExp.pm | 5 +- perl-xCAT/xCAT/TableUtils.pm | 112 ++++++++++++++++++++++++++++--- perl-xCAT/xCAT/Zone.pm | 2 +- 3 files changed, 105 insertions(+), 14 deletions(-) diff --git a/perl-xCAT/xCAT/RemoteShellExp.pm b/perl-xCAT/xCAT/RemoteShellExp.pm index 4d9b3d34d..925465dc0 100755 --- a/perl-xCAT/xCAT/RemoteShellExp.pm +++ b/perl-xCAT/xCAT/RemoteShellExp.pm @@ -495,6 +495,7 @@ sub sendnodeskeys # in $HOME/.ssh/tmp/authorized_keys # copy to the node to the temp directory # scp $HOME/.ssh/tmp/authorized_keys to_userid@:/tmp/$to_userid/.ssh + # scp $HOME/.ssh/id_rsa.pub to_userid@:/tmp/$to_userid/.ssh # If you are going to enable ssh to ssh between nodes, then # scp $HOME/.ssh/id_rsa to that temp directory on the node # copy the script $HOME/.ssh/copy.sh to the node, it will do the @@ -607,11 +608,11 @@ sub sendnodeskeys my $spawncopyfiles; if ($ENV{'DSH_ENABLE_SSH'}) { # we will enable node to node ssh $spawncopyfiles= - "$remotecopy $home/.ssh/id_rsa $home/.ssh/copy.sh $home/.ssh/tmp/authorized_keys $to_userid\@$node:/tmp/$to_userid/.ssh "; + "$remotecopy $home/.ssh/id_rsa $home/.ssh/id_rsa.pub $home/.ssh/copy.sh $home/.ssh/tmp/authorized_keys $to_userid\@$node:/tmp/$to_userid/.ssh "; } else { # no node to node ssh ( don't send private key) $spawncopyfiles= - "$remotecopy $home/.ssh/copy.sh $home/.ssh/tmp/authorized_keys $to_userid\@$node:/tmp/$to_userid/.ssh "; + "$remotecopy $home/.ssh/id_rsa.pub $home/.ssh/copy.sh $home/.ssh/tmp/authorized_keys $to_userid\@$node:/tmp/$to_userid/.ssh "; } # send copy command unless ($sendkeys->spawn($spawncopyfiles)) diff --git a/perl-xCAT/xCAT/TableUtils.pm b/perl-xCAT/xCAT/TableUtils.pm index 9e3b452ad..b44cb6f27 100644 --- a/perl-xCAT/xCAT/TableUtils.pm +++ b/perl-xCAT/xCAT/TableUtils.pm @@ -19,6 +19,7 @@ if ($^O =~ /^aix/i) { use lib "$::XCATROOT/lib/perl"; use strict; require xCAT::Table; +require xCAT::Zone; use File::Path; #----------------------------------------------------------------------- @@ -271,7 +272,7 @@ sub bldnonrootSSHFiles Error: 0=good, 1=error Example: - xCAT::TableUtils->setupSSH(@target_nodes); + xCAT::TableUtils->setupSSH(@target_nodes,$expecttimeout); Comments: Does not setup known_hosts. Assumes automatically setup by SSH ( ssh config option StrictHostKeyChecking no should @@ -335,21 +336,21 @@ sub setupSSH $::REMOTE_SHELL = "/usr/bin/ssh"; my $rsp = {}; + # Get the home directory my $home = xCAT::Utils->getHomeDir($from_userid); $ENV{'DSH_FROM_USERID_HOME'} = $home; - if ($from_userid eq "root") { - # make the directory to hold keys to transfer to the nodes if (!-d $SSHdir) { mkpath("$SSHdir", { mode => 0755 }); } - # generates new keys for root, if they do not already exist + # generates new keys for root, if they do not already exist ~/.ssh + # nodes not used on this option but in there to preserve the interface my $rc= xCAT::RemoteShellExp->remoteshellexp("k",$::CALLBACK,$::REMOTE_SHELL,$n_str,$expecttimeout); @@ -374,7 +375,9 @@ else fi mkdir -p \$dest_dir cat /tmp/$to_userid/.ssh/authorized_keys >> \$home/.ssh/authorized_keys 2>&1 +cat /tmp/$to_userid/.ssh/id_rsa.pub >> \$home/.ssh/authorized_keys 2>&1 cp /tmp/$to_userid/.ssh/id_rsa \$home/.ssh/id_rsa 2>&1 +cp /tmp/$to_userid/.ssh/id_rsa.pub \$home/.ssh/id_rsa.pub 2>&1 chmod 0600 \$home/.ssh/id_* 2>&1 rm -f /tmp/$to_userid/.ssh/* 2>&1 rmdir \"/tmp/$to_userid/.ssh\" @@ -386,6 +389,7 @@ rmdir \"/tmp/$to_userid\" \n"; my $auth_key2=0; if ($from_userid eq "root") { + # this will put the root/.ssh/id_rsa.pub key in the authorized keys file to put on the node my $rc = xCAT::TableUtils->cpSSHFiles($SSHdir); if ($rc != 0) { # error @@ -418,13 +422,43 @@ rmdir \"/tmp/$to_userid\" \n"; xCAT::TableUtils->bldnonrootSSHFiles($from_userid); } - # send the keys to the nodes for root or some other id - # - # This environment variable determines whether to setup - # node to node ssh - # The nodes must be checked against the site.sshbetweennodes attribute # For root user and not to devices only to nodes if (($from_userid eq "root") && (!($ENV{'DEVICETYPE'}))) { + # Need to check if nodes are in a zone. + # If in a zone, then root ssh keys for the node will be taken from the zones ssh keys not ~/.ssh + # zones are only supported on nodes that are not a service node. + # Also for the call to RemoteShellExp, we must group the nodes that are in the same zone + + my $tab = xCAT::Table->new("zone"); + if ($tab) + { + # if we have zones, need to send the zone keys to each node in the zone + my @zones = $tab->getAllAttribs('zonename'); + $tab->close(); + if (@zones) { # we have zones defined + my $rc = xCAT::TableUtils->sendkeystozones($ref_nodes,$expecttimeout); + if ($rc != 0) + { + $rsp->{data}->[0] = "Error sending ssh keys to the zones.\n"; + xCAT::MsgUtils->message("E", $rsp, $::CALLBACK); + return 1; + + } + return 0; + } + } else { + $rsp->{data}->[0] = "Could not open zone table.\n"; + xCAT::MsgUtils->message("E", $rsp, $::CALLBACK); + return 1; + } + + + # if no zone table defined, do it the old way + # send the keys to the nodes for root or some other id + # + # The nodes must be checked against the site.sshbetweennodes attribute + # This site attribute determines whether to setup + # node to node ssh my $enablenodes; my $disablenodes; my @nodelist= split(",", $n_str); @@ -440,10 +474,10 @@ rmdir \"/tmp/$to_userid\" \n"; } } - my $cmd; if ($enablenodes) { # node on list to setup nodetonodessh chop $enablenodes; # remove last comma $ENV{'DSH_ENABLE_SSH'} = "YES"; + # send the keys to the nodes my $rc=xCAT::RemoteShellExp->remoteshellexp("s",$::CALLBACK,"/usr/bin/ssh",$enablenodes,$expecttimeout); if ($rc != 0) { @@ -452,8 +486,9 @@ rmdir \"/tmp/$to_userid\" \n"; } } - if ($disablenodes) { # node on list to setup nodetonodessh + if ($disablenodes) { # node on list to disable nodetonodessh chop $disablenodes; # remove last comma + # send the keys to the nodes my $rc=xCAT::RemoteShellExp->remoteshellexp("s",$::CALLBACK,"/usr/bin/ssh",$disablenodes,$expecttimeout); if ($rc != 0) { @@ -462,6 +497,7 @@ rmdir \"/tmp/$to_userid\" \n"; } } + } else { # from user is not root or it is a device , always send private key $ENV{'DSH_ENABLE_SSH'} = "YES"; my $rc=xCAT::RemoteShellExp->remoteshellexp("s",$::CALLBACK,"/usr/bin/ssh",$n_str,$expecttimeout); @@ -503,6 +539,60 @@ rmdir \"/tmp/$to_userid\" \n"; #-------------------------------------------------------------------------------- +=head3 sendkeystozones + + Transfers the ssh keys + for the root id on the nodes using the zone table. + + + Arguments: + Array of nodes + Timeout for expect call (optional) + Returns: + + Env Variables: $DSH_FROM_USERID, $DSH_TO_USERID, $DSH_REMOTE_PASSWORD + the ssh keys are transferred from the $DSH_FROM_USERID to the $DSH_TO_USERID + on the node(s). The DSH_REMOTE_PASSWORD and the DSH_FROM_USERID + must be obtained by + the calling script or from the xdsh client + + Globals: + $::XCATROOT , $::CALLBACK + Error: + 0=good, 1=error + Example: + xCAT::TableUtils->setupSSH(@target_nodes,$expecttimeout); + Comments: + Does not setup known_hosts. Assumes automatically + setup by SSH ( ssh config option StrictHostKeyChecking no should + be set in the ssh config file). + +=cut + +#-------------------------------------------------------------------------------- +sub sendkeystozones +{ + my ($class, $ref_nodes,$expecttimeout) = @_; + my @nodes=$ref_nodes; + my %zonehash =xCAT::Zone->getNodeZones(@nodes); + # for each zone in the zonehash + # if sshbetweennodes is yes + # $ENV{'DSH_ENABLE_SSH'} = "YES"; + # else + # unset $ENV{'DSH_ENABLE_SSH'} + # send the keys to the nodes + # my $rc=xCAT::RemoteShellExp->remoteshellexp("s",$::CALLBACK,"/usr/bin/ssh",$nodelist,$expecttimeout); + # if ($rc != 0) + # { + # $rsp->{data}->[0] = "remoteshellexp failed sending keys to $zonename."; + # xCAT::MsgUtils->message("E", $rsp, $::CALLBACK); + # + # } + # } # endforeach + return 0; +} +#-------------------------------------------------------------------------------- + =head3 cpSSHFiles Builds authorized_keyfiles for root diff --git a/perl-xCAT/xCAT/Zone.pm b/perl-xCAT/xCAT/Zone.pm index 6c5c06eb6..e974a366d 100644 --- a/perl-xCAT/xCAT/Zone.pm +++ b/perl-xCAT/xCAT/Zone.pm @@ -249,7 +249,7 @@ sub iszonedefined -> {sshkeydir} -> directory containing ssh RSA keys -> {defaultzone} -> is it the default zone Example: - my %zonehash =xCAT::Zone->getNodeZones($nodelist); + my %zonehash =xCAT::Zone->getNodeZones(@nodearray); Rules: If the nodes nodelist.zonename attribute is a zonename, it is assigned to that zone If the nodes nodelist.zonename attribute is undefined: