7ee8876bfd
git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@13607 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd
729 lines
21 KiB
Perl
729 lines
21 KiB
Perl
#!/usr/bin/env perl
|
|
# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
|
|
package xCAT::ServiceNodeUtils;
|
|
|
|
BEGIN
|
|
{
|
|
$::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat';
|
|
}
|
|
|
|
# if AIX - make sure we include perl 5.8.2 in INC path.
|
|
# Needed to find perl dependencies shipped in deps tarball.
|
|
if ($^O =~ /^aix/i) {
|
|
use lib "/usr/opt/perl5/lib/5.8.2/aix-thread-multi";
|
|
use lib "/usr/opt/perl5/lib/5.8.2";
|
|
use lib "/usr/opt/perl5/lib/site_perl/5.8.2/aix-thread-multi";
|
|
use lib "/usr/opt/perl5/lib/site_perl/5.8.2";
|
|
}
|
|
|
|
use lib "$::XCATROOT/lib/perl";
|
|
#-----------------------------------------------------------------------------
|
|
|
|
=head3 readSNInfo
|
|
|
|
Read resource, NFS server, Master node, OS an ARCH from the database
|
|
for the service node
|
|
|
|
Input: service nodename
|
|
Output: Masternode, OS and ARCH
|
|
Example:
|
|
xCAT::ServiceNodeUtils->readSNInfo;
|
|
=cut
|
|
|
|
#-----------------------------------------------------------------------------
|
|
sub readSNInfo
|
|
{
|
|
my ($class, $nodename) = @_;
|
|
my $rc = 0;
|
|
my $et;
|
|
my $masternode;
|
|
my $os;
|
|
my $arch;
|
|
$rc = xCAT::Utils->exportDBConfig();
|
|
if ($rc == 0)
|
|
{
|
|
|
|
if ($nodename)
|
|
{
|
|
$masternode = xCAT::TableUtils->GetMasterNodeName($nodename);
|
|
if (!($masternode))
|
|
{
|
|
xCAT::MsgUtils->message('S',
|
|
"Could not get Master for node $nodename\n");
|
|
return 1;
|
|
}
|
|
|
|
$et = xCAT::TableUtils->GetNodeOSARCH($nodename);
|
|
if ($et == 1)
|
|
{
|
|
xCAT::MsgUtils->message('S',
|
|
"Could not get OS/ARCH for node $nodename\n");
|
|
return 1;
|
|
}
|
|
if (!($et->{'os'} || $et->{'arch'}))
|
|
{
|
|
xCAT::MsgUtils->message('S',
|
|
"Could not get OS/ARCH for node $nodename\n");
|
|
return 1;
|
|
}
|
|
}
|
|
$et->{'master'} = $masternode;
|
|
return $et;
|
|
}
|
|
return $rc;
|
|
}
|
|
|
|
#-----------------------------------------------------------------------------
|
|
|
|
=head3 isServiceReq
|
|
|
|
|
|
Checks the service node table in the database to see
|
|
if input Service should be setup on the
|
|
input service node
|
|
|
|
Input:servicenodename,ipaddres(s) and hostnames of service node
|
|
Output:
|
|
array of services to setup for this service node
|
|
Globals:
|
|
$::RUNCMD_RC = 0; good
|
|
$::RUNCMD_RC = 1; error
|
|
Error:
|
|
none
|
|
Example:
|
|
@servicestosetup=xCAT::ServiceNodeUtils->isServiceReq($servicenodename, @serviceip) { blah; }
|
|
|
|
=cut
|
|
|
|
#-----------------------------------------------------------------------------
|
|
sub isServiceReq
|
|
{
|
|
require xCAT::Table;
|
|
my ($class, $servicenodename, $serviceip) = @_;
|
|
|
|
# list of all services from service node table
|
|
# note this must be updated if more services added
|
|
my @services = (
|
|
"nameserver", "dhcpserver", "tftpserver", "nfsserver",
|
|
"conserver", "monserver", "ldapserver", "ntpserver",
|
|
"ftpserver", "ipforward"
|
|
);
|
|
|
|
my @ips = @$serviceip; # list of service node ip addresses and names
|
|
my $rc = 0;
|
|
|
|
$rc = xCAT::Utils->exportDBConfig(); # export DB env
|
|
if ($rc != 0)
|
|
{
|
|
xCAT::MsgUtils->message('S', "Unable export DB environment.\n");
|
|
$::RUNCMD_RC = 1;
|
|
return;
|
|
|
|
}
|
|
|
|
# get handle to servicenode table
|
|
my $servicenodetab = xCAT::Table->new('servicenode');
|
|
unless ($servicenodetab)
|
|
{
|
|
xCAT::MsgUtils->message('S', "Unable to open servicenode table.\n");
|
|
$::RUNCMD_RC = 1;
|
|
return; # do not setup anything
|
|
}
|
|
|
|
my @process_service_list = ();
|
|
|
|
# read all the nodes from the table, for each service
|
|
foreach my $service (@services)
|
|
{
|
|
my @snodelist = $servicenodetab->getAllNodeAttribs([$service]);
|
|
|
|
foreach $serviceip (@ips) # check the table for this servicenode
|
|
{
|
|
foreach my $node (@snodelist)
|
|
|
|
{
|
|
if ($serviceip eq $node->{'node'})
|
|
{ # match table entry
|
|
if ($node->{$service})
|
|
{ # returns service, only if set
|
|
my $value = $node->{$service};
|
|
$value =~ tr/a-z/A-Z/; # convert to upper
|
|
# value 1 or yes then we setup the service
|
|
if (($value eq "1") || ($value eq "YES"))
|
|
{
|
|
push @process_service_list,
|
|
$service; # found service to setup
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
$servicenodetab->close;
|
|
|
|
$::RUNCMD_RC = 0;
|
|
return @process_service_list;
|
|
|
|
}
|
|
|
|
#-----------------------------------------------------------------------------
|
|
|
|
=head3 getAllSN
|
|
|
|
Returns an array of all service nodes from service node table
|
|
|
|
Arguments:
|
|
none
|
|
Returns:
|
|
array of Service Nodes or empty array, if none
|
|
Globals:
|
|
none
|
|
Error:
|
|
1 - error
|
|
Example:
|
|
@allSN=xCAT::ServiceNodeUtils->getAllSN
|
|
Comments:
|
|
none
|
|
|
|
=cut
|
|
|
|
#-----------------------------------------------------------------------------
|
|
sub getAllSN
|
|
{
|
|
|
|
require xCAT::Table;
|
|
# reads all nodes from the service node table
|
|
my @servicenodes;
|
|
my $servicenodetab = xCAT::Table->new('servicenode');
|
|
unless ($servicenodetab) # no servicenode table
|
|
{
|
|
xCAT::MsgUtils->message('I', "Unable to open servicenode table.\n");
|
|
$servicenodetab->close;
|
|
return @servicenodes;
|
|
|
|
}
|
|
my @nodes = $servicenodetab->getAllNodeAttribs(['tftpserver']);
|
|
foreach my $nodes (@nodes)
|
|
{
|
|
push @servicenodes, $nodes->{node};
|
|
}
|
|
$servicenodetab->close;
|
|
return @servicenodes;
|
|
}
|
|
|
|
#-----------------------------------------------------------------------------
|
|
|
|
=head3 getSNandNodes
|
|
|
|
Returns an hash-array of all service nodes and the nodes they service
|
|
|
|
Arguments:
|
|
none
|
|
#-----------------------------------------------------------------------------
|
|
|
|
=head3 getSNandNodes
|
|
|
|
Returns an hash-array of all service nodes and the nodes they service
|
|
|
|
Arguments:
|
|
none
|
|
Returns:
|
|
Service Nodes and the nodes they service or empty , if none
|
|
Globals:
|
|
none
|
|
Error:
|
|
1 - error
|
|
Example:
|
|
$sn=xCAT::ServiceNodeUtils->getSNandNodes()
|
|
Comments:
|
|
none
|
|
|
|
=cut
|
|
|
|
#-----------------------------------------------------------------------------
|
|
sub getSNandNodes
|
|
{
|
|
|
|
require xCAT::Table;
|
|
# read all the nodes from the nodelist table
|
|
# call get_ServiceNode to find which Service Node
|
|
# the node belongs to.
|
|
my %sn;
|
|
my @nodes;
|
|
my $nodelisttab = xCAT::Table->new('nodelist');
|
|
my $recs = $nodelisttab->getAllEntries();
|
|
foreach (@$recs)
|
|
{
|
|
push @nodes, $_->{node};
|
|
}
|
|
$nodelisttab->close;
|
|
my $sn = xCAT::ServiceNodeUtils->get_ServiceNode(\@nodes, "xcat", "MN");
|
|
return $sn;
|
|
}
|
|
|
|
#-----------------------------------------------------------------------------
|
|
|
|
=head3 getSNList
|
|
|
|
Reads the servicenode table. Will return all the enabled Service Nodes
|
|
that will setup the input Service ( e.g tftpserver,nameserver,etc)
|
|
If service is blank, then will return the list of all enabled Service
|
|
Nodes.
|
|
|
|
Arguments:
|
|
Servicename ( xcat,tftpserver,dhcpserver,conserver,etc)
|
|
Returns:
|
|
Array of service node names
|
|
Globals:
|
|
none
|
|
Error:
|
|
1 - error
|
|
Example:
|
|
$sn= xCAT::ServiceNodeUtils->getSNList($servicename) { blah; }
|
|
$sn= xCAT::ServiceNodeUtils->getSNList() { blah; }
|
|
Comments:
|
|
none
|
|
|
|
=cut
|
|
|
|
#-----------------------------------------------------------------------------
|
|
sub getSNList
|
|
{
|
|
require xCAT::Table;
|
|
my ($class, $service) = @_;
|
|
|
|
# reads all nodes from the service node table
|
|
my @servicenodes;
|
|
my $servicenodetab = xCAT::Table->new('servicenode', -create => 1);
|
|
unless ($servicenodetab) # no servicenode table
|
|
{
|
|
xCAT::MsgUtils->message('I', "Unable to open servicenode table.\n");
|
|
return ();
|
|
}
|
|
my @nodes = $servicenodetab->getAllNodeAttribs([$service]);
|
|
$servicenodetab->close;
|
|
foreach my $node (@nodes)
|
|
{
|
|
if ($service eq "") # want all the service nodes
|
|
{
|
|
push @servicenodes, $node->{node};
|
|
}
|
|
else
|
|
{ # looking for a particular service
|
|
if ($node->{$service})
|
|
{ # if null then do not add node
|
|
my $value = $node->{$service};
|
|
$value =~ tr/a-z/A-Z/; # convert to upper
|
|
# value 1 or yes or blank then we setup the service
|
|
if (($value == 1) || ($value eq "YES"))
|
|
{
|
|
push @servicenodes, $node->{node};
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return @servicenodes;
|
|
}
|
|
|
|
|
|
#-----------------------------------------------------------------------------
|
|
|
|
=head3 get_ServiceNode
|
|
|
|
Will get the Service node ( name or ipaddress) as known by the Management
|
|
Node or Node for the input nodename or ipadress of the node
|
|
which can be a Service Node.
|
|
If the input node is a Service Node then it's Service node
|
|
is always the Management Node.
|
|
|
|
input: list of nodenames and/or node ipaddresses (array ref)
|
|
service name
|
|
"MN" or "Node" determines if you want the Service node as known
|
|
by the Management Node or by the node.
|
|
|
|
recognized service names: xcat,tftpserver,
|
|
nfsserver,conserver,monserver
|
|
|
|
service "xcat" is used by command like xdsh that need to know the
|
|
service node that will process the command but are not tied to a
|
|
specific service like tftp
|
|
|
|
Todo: Handle dhcpserver and nameserver from the networks table
|
|
|
|
output: A hash ref of arrays, the key is the service node pointing to
|
|
an array of nodes that are serviced by that service node
|
|
|
|
Globals:
|
|
$::ERROR_RC
|
|
Error:
|
|
$::ERROR_RC=0 no error $::ERROR_RC=1 error
|
|
|
|
example: $sn =xCAT::ServiceNodeUtils->get_ServiceNode(\@nodes,$service,"MN");
|
|
$sn =xCAT::ServiceNodeUtils->get_ServiceNode(\@nodes,$service,"Node");
|
|
Note: this rountine is important to hierarchical support in xCAT
|
|
and used in many places. Any changes to the logic should be
|
|
reviewed by xCAT architecture
|
|
=cut
|
|
|
|
#-----------------------------------------------------------------------------
|
|
sub get_ServiceNode
|
|
{
|
|
require xCAT::Table;
|
|
my ($class, $node, $service, $request) = @_;
|
|
my @node_list = @$node;
|
|
my $cmd;
|
|
my %snhash;
|
|
my $nodehash;
|
|
my $sn;
|
|
my $nodehmtab;
|
|
my $noderestab;
|
|
my $snattribute;
|
|
my $oshash;
|
|
my $nodetab;
|
|
$::ERROR_RC = 0;
|
|
|
|
# determine if the request is for the service node as known by the MN
|
|
# or the node
|
|
|
|
if ($request eq "MN")
|
|
{
|
|
$snattribute = "servicenode";
|
|
|
|
}
|
|
else # Node
|
|
{
|
|
$snattribute = "xcatmaster";
|
|
}
|
|
# get site.master this will be the default
|
|
my $master = xCAT::TableUtils->get_site_Master();
|
|
$noderestab = xCAT::Table->new('noderes');
|
|
|
|
unless ($noderestab) # no noderes table, use default site.master
|
|
{
|
|
xCAT::MsgUtils->message('I',
|
|
"Unable to open noderes table. Using site->Master.\n");
|
|
|
|
if ($master) # use site Master value
|
|
{
|
|
|
|
foreach my $node (@node_list)
|
|
{
|
|
push @{$snhash{$master}}, $node;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
xCAT::MsgUtils->message('E', "Unable to read site Master value.\n");
|
|
$::ERROR_RC = 1;
|
|
}
|
|
|
|
return \%snhash;
|
|
}
|
|
|
|
if ($service eq "xcat")
|
|
{ # find all service nodes for the nodes in the list
|
|
|
|
$nodehash = $noderestab->getNodesAttribs(\@node_list, [$snattribute]);
|
|
|
|
|
|
foreach my $node (@node_list)
|
|
{
|
|
foreach my $rec (@{$nodehash->{$node}})
|
|
{
|
|
if ($rec and $rec->{$snattribute}) # use noderes.servicenode
|
|
{
|
|
my $key = $rec->{$snattribute};
|
|
push @{$snhash{$key}}, $node;
|
|
}
|
|
else # use site.master
|
|
{
|
|
push @{$snhash{$master}}, $node;
|
|
}
|
|
}
|
|
}
|
|
|
|
$noderestab->close;
|
|
return \%snhash;
|
|
|
|
}
|
|
else
|
|
{
|
|
if (
|
|
($service eq "tftpserver") # all from noderes table
|
|
|| ($service eq "nfsserver") || ($service eq "monserver")
|
|
)
|
|
{
|
|
$nodehash =
|
|
$noderestab->getNodesAttribs(\@node_list,
|
|
[$service, $snattribute]);
|
|
foreach my $node (@node_list)
|
|
{
|
|
foreach my $rec (@{$nodehash->{$node}})
|
|
{
|
|
if ($rec and $rec->{$service})
|
|
{
|
|
|
|
# see if both MN and Node address in attribute
|
|
my ($msattr, $nodeattr) = split ':', $rec->{$service};
|
|
my $key = $msattr;
|
|
if ($request eq "Node")
|
|
{
|
|
if ($nodeattr) # override with Node, if it exists
|
|
{
|
|
$key = $nodeattr;
|
|
}
|
|
}
|
|
push @{$snhash{$key}}, $node;
|
|
}
|
|
else
|
|
{
|
|
if ($rec and $rec->{$snattribute}) # if it exists
|
|
{
|
|
my $key = $rec->{$snattribute};
|
|
push @{$snhash{$key}}, $node;
|
|
}
|
|
else
|
|
{ # use site.master
|
|
push @{$snhash{$master}}, $node;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
$noderestab->close;
|
|
return \%snhash;
|
|
|
|
}
|
|
else
|
|
{
|
|
if ($service eq "conserver")
|
|
{
|
|
|
|
# read the nodehm table
|
|
$nodehmtab = xCAT::Table->new('nodehm');
|
|
unless ($nodehmtab) # no nodehm table
|
|
{
|
|
xCAT::MsgUtils->message('I',
|
|
"Unable to open nodehm table.\n");
|
|
|
|
# use servicenode
|
|
$nodehash =
|
|
$noderestab->getNodesAttribs(\@node_list, [$snattribute]);
|
|
foreach my $node (@node_list)
|
|
{
|
|
foreach my $rec (@{$nodehash->{$node}})
|
|
{
|
|
if ($rec and $rec->{$snattribute})
|
|
{
|
|
my $key = $rec->{$snattribute};
|
|
push @{$snhash{$key}}, $node;
|
|
}
|
|
else
|
|
{ # use site.master
|
|
push @{$snhash{$master}}, $node;
|
|
}
|
|
}
|
|
}
|
|
$noderestab->close;
|
|
return \%snhash;
|
|
}
|
|
|
|
# can read the nodehm table
|
|
$nodehash =
|
|
$nodehmtab->getNodesAttribs(\@node_list, ['conserver']);
|
|
foreach my $node (@node_list)
|
|
{
|
|
foreach my $rec (@{$nodehash->{$node}})
|
|
{
|
|
if ($rec and $rec->{'conserver'})
|
|
{
|
|
|
|
# see if both MN and Node address in attribute
|
|
my ($msattr, $nodeattr) = split ':',
|
|
$rec->{'conserver'};
|
|
my $key = $msattr;
|
|
if ($request eq "Node")
|
|
{
|
|
if ($nodeattr
|
|
) # override with Node, if it exists
|
|
{
|
|
$key = $nodeattr;
|
|
}
|
|
}
|
|
push @{$snhash{$key}}, $node;
|
|
}
|
|
else
|
|
{ # use service node for this node
|
|
$sn =
|
|
$noderestab->getNodeAttribs($node,
|
|
[$snattribute]);
|
|
if ($sn and $sn->{$snattribute})
|
|
{
|
|
my $key = $sn->{$snattribute};
|
|
push @{$snhash{$key}}, $node;
|
|
}
|
|
else
|
|
{ # no service node use master
|
|
push @{$snhash{$master}}, $node;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
$noderestab->close;
|
|
$nodehmtab->close;
|
|
return \%snhash;
|
|
|
|
}
|
|
else
|
|
{
|
|
xCAT::MsgUtils->message('E',
|
|
"Invalid service=$service input.\n");
|
|
$::ERROR_RC = 1;
|
|
}
|
|
}
|
|
}
|
|
return \%snhash;
|
|
|
|
}
|
|
|
|
|
|
#-----------------------------------------------------------------------------
|
|
|
|
=head3 getSNformattedhash
|
|
|
|
Will call get_ServiceNode to get the Service node ( name or ipaddress)
|
|
as known by the Management
|
|
Server or Node for the input nodename or ipadress of the node
|
|
It will then format the output into a single servicenode key with values
|
|
the list of nodes service by that service node. This routine will
|
|
break up pools of service nodes into individual node in the hash unlike
|
|
get_ServiceNode which leaves the pool as the key.
|
|
|
|
input: Same as get_ServiceNode to call get_ServiceNode
|
|
list of nodenames and/or node ipaddresses (array ref)
|
|
service name
|
|
"MN" or "Node" determines if you want the Service node as known
|
|
by the Management Node or by the node.
|
|
|
|
recognized service names: xcat,tftpserver,
|
|
nfsserver,conserver,monserver
|
|
|
|
service "xcat" is used by command like xdsh that need to know the
|
|
service node that will process the command but are not tied to a
|
|
specific service like tftp
|
|
|
|
|
|
output: A hash ref of arrays, the key is a single service node
|
|
pointing to
|
|
a list of nodes that are serviced by that service node
|
|
'rra000-m'=>['blade01', 'testnode']
|
|
'sn1'=>['blade01', 'testnode']
|
|
'sn2'=>['blade01']
|
|
'sn3'=>['testnode']
|
|
|
|
Globals:
|
|
$::ERROR_RC
|
|
Error:
|
|
$::ERROR_RC=0 no error $::ERROR_RC=1 error
|
|
|
|
example: $sn =xCAT::ServiceNodeUtils->getSNformattedhash(\@nodes,$service,"MN", $type);
|
|
$sn =xCAT::ServiceNodeUtils->getSNformattedhash(\@nodes,$service,"Node", "primary");
|
|
|
|
=cut
|
|
|
|
#-----------------------------------------------------------------------------
|
|
sub getSNformattedhash
|
|
{
|
|
my ($class, $node, $service, $request, $btype) = @_;
|
|
my @node_list = @$node;
|
|
my $cmd;
|
|
my %newsnhash;
|
|
|
|
my $type="";
|
|
if ($btype) {
|
|
$type=$btype;
|
|
}
|
|
|
|
# get the values of either the servicenode or xcatmaster attributes
|
|
my $sn = xCAT::ServiceNodeUtils->get_ServiceNode(\@node_list, $service, $request);
|
|
|
|
# get the keys which are the service nodes and break apart any pool lists
|
|
# format into individual service node keys pointing to node lists
|
|
if ($sn)
|
|
{
|
|
foreach my $snkey (keys %$sn)
|
|
{
|
|
# split the key if pool of service nodes
|
|
push my @tmpnodes, $sn->{$snkey};
|
|
my @nodes;
|
|
for my $i (0 .. $#tmpnodes) {
|
|
for my $j ( 0 .. $#{$tmpnodes[$i]}) {
|
|
my $check=$tmpnodes[$i][$j];
|
|
push @nodes,$check;
|
|
}
|
|
}
|
|
|
|
# for SN backup we might only want the primary or backup
|
|
my @servicenodes;
|
|
my ($primary, $backup) = split /,/, $snkey;
|
|
if (($primary) && ($type eq "primary")) {
|
|
push @servicenodes, $primary;
|
|
} elsif (($backup) && ($type eq "backup")) {
|
|
push @servicenodes, $backup;
|
|
} else {
|
|
@servicenodes = split /,/, $snkey;
|
|
}
|
|
|
|
# now build new hash of individual service nodes
|
|
foreach my $newsnkey (@servicenodes) {
|
|
push @{$newsnhash{$newsnkey}}, @nodes;
|
|
}
|
|
}
|
|
}
|
|
return \%newsnhash;
|
|
}
|
|
#-----------------------------------------------------------------------------
|
|
|
|
=head3
|
|
|
|
getSNandCPnodes - Take an array of nodes and returns
|
|
an array of the service
|
|
nodes and an array of the computenode .
|
|
|
|
Arguments:
|
|
none
|
|
Returns:
|
|
array of Service Nodes and/or array of compute nodesarray of compute nodes empty array, if none
|
|
Globals:
|
|
none
|
|
Error:
|
|
1 - error
|
|
Example:
|
|
xCAT::ServiceNodeUtils->getSNandCPnodes(\@nodes,\@SN,\@CN);
|
|
Comments:
|
|
none
|
|
|
|
=cut
|
|
|
|
#-----------------------------------------------------------------------------
|
|
sub getSNandCPnodes
|
|
{
|
|
|
|
my ($class, $nodes,$sn,$cn) = @_;
|
|
my @nodelist = @$nodes;
|
|
# get the list of all Service nodes
|
|
@allSN=xCAT::ServiceNodeUtils->getAllSN;
|
|
foreach $node (@nodelist) {
|
|
if (grep(/^$node$/, @allSN)) { # it is a SN
|
|
push (@$sn,$node);
|
|
} else { # a CN
|
|
push (@$cn,$node);
|
|
}
|
|
}
|
|
|
|
return ;
|
|
}
|
|
1;
|