From 571f3e3962e6636813a58f2f017e878cb1488653 Mon Sep 17 00:00:00 2001 From: zhaoertao Date: Thu, 9 Aug 2012 03:48:50 +0000 Subject: [PATCH] for item: clean up Utils.pm, the code in perl-xCAT/xCAT git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@13461 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd --- perl-xCAT/xCAT/Client.pm | 4 +- perl-xCAT/xCAT/DSHCLI.pm | 7 +- perl-xCAT/xCAT/FSPUtils.pm | 7 +- perl-xCAT/xCAT/FSPcfg.pm | 7 +- perl-xCAT/xCAT/InstUtils.pm | 14 +- perl-xCAT/xCAT/MacMap.pm | 5 +- perl-xCAT/xCAT/NetworkUtils.pm | 1351 ++++++++++- perl-xCAT/xCAT/PPCboot.pm | 3 +- perl-xCAT/xCAT/PPCcfg.pm | 5 +- perl-xCAT/xCAT/PPCcli.pm | 4 +- perl-xCAT/xCAT/PPCconn.pm | 7 +- perl-xCAT/xCAT/PPCdb.pm | 16 +- perl-xCAT/xCAT/PPCenergy.pm | 8 +- perl-xCAT/xCAT/PPCfsp.pm | 4 +- perl-xCAT/xCAT/PPCmac.pm | 11 +- perl-xCAT/xCAT/PPCrflash.pm | 4 +- perl-xCAT/xCAT/RSYNC.pm | 4 +- perl-xCAT/xCAT/Scope.pm | 7 +- perl-xCAT/xCAT/ServiceNodeUtils.pm | 685 ++++++ perl-xCAT/xCAT/TableUtils.pm | 1471 ++++++++++++ perl-xCAT/xCAT/Utils.pm | 3560 +--------------------------- 21 files changed, 3572 insertions(+), 3612 deletions(-) create mode 100644 perl-xCAT/xCAT/ServiceNodeUtils.pm create mode 100644 perl-xCAT/xCAT/TableUtils.pm diff --git a/perl-xCAT/xCAT/Client.pm b/perl-xCAT/xCAT/Client.pm index 2a2cbaef8..a5ad6e221 100644 --- a/perl-xCAT/xCAT/Client.pm +++ b/perl-xCAT/xCAT/Client.pm @@ -714,7 +714,7 @@ sub dispatch_request { if (ref $_->{'_xcatdest'} and (ref $_->{'_xcatdest'}) eq 'ARRAY') { _->{'_xcatdest'} = $_->{'_xcatdest'}->[0]; } - if ($onlyone and not ($_->{'_xcatdest'} and xCAT::Utils->thishostisnot($_->{'_xcatdest'}))) { + if ($onlyone and not ($_->{'_xcatdest'} and xCAT::NetworkUtils->thishostisnot($_->{'_xcatdest'}))) { $SIG{CHLD}='DEFAULT'; ${"xCAT_plugin::".$modname."::"}{process_request}->($_,$dispatch_cb,\&do_request); return; @@ -755,7 +755,7 @@ sub dispatch_request { my $request_satisfied=0; foreach $xcatdest (@xcatdests) { my $dlock; - if ($xcatdest and xCAT::Utils->thishostisnot($xcatdest)) { + if ($xcatdest and xCAT::NetworkUtils->thishostisnot($xcatdest)) { #----- added to Client.pm -----# $dispatch_cb->({warning=>['XCATBYPASS is set, skipping hierarchy call to '.$_->{'_xcatdest'}.'']}); #----- end added to Client.pm -----# diff --git a/perl-xCAT/xCAT/DSHCLI.pm b/perl-xCAT/xCAT/DSHCLI.pm index ae250a582..a32c9f5d5 100644 --- a/perl-xCAT/xCAT/DSHCLI.pm +++ b/perl-xCAT/xCAT/DSHCLI.pm @@ -14,6 +14,7 @@ use Getopt::Long; require xCAT::DSHCore; use xCAT::MsgUtils; use xCAT::Utils; +use xCAT::TableUtils; use lib '/opt/xcat/xdsh'; our @dsh_available_contexts = (); our @dsh_valid_contexts = (); @@ -3906,7 +3907,7 @@ sub parse_and_run_dsh # # setup ssh keys on the nodes or ib switch # - my $rc = xCAT::Utils->setupSSH($options{'nodes'}); + my $rc = xCAT::TableUtils->setupSSH($options{'nodes'}); my @results = "return code = $rc"; return (@results); } @@ -4262,13 +4263,13 @@ sub parse_and_run_dcp $nodesyncfiledir = "/var/xcat/node/syncfiles"; # get the directory on the servicenode to put the rsync files in - my @syndir = xCAT::Utils->get_site_attribute("SNsyncfiledir"); + my @syndir = xCAT::TableUtils->get_site_attribute("SNsyncfiledir"); if ($syndir[0]) { $synfiledir = $syndir[0]; } # get the directory on the node to put the rsync files in - my @syndir = xCAT::Utils->get_site_attribute("nodesyncfiledir"); + my @syndir = xCAT::TableUtils->get_site_attribute("nodesyncfiledir"); if ($syndir[0]) { $nodesyncfiledir = $syndir[0]; diff --git a/perl-xCAT/xCAT/FSPUtils.pm b/perl-xCAT/xCAT/FSPUtils.pm index db4704812..8236c826b 100644 --- a/perl-xCAT/xCAT/FSPUtils.pm +++ b/perl-xCAT/xCAT/FSPUtils.pm @@ -23,6 +23,7 @@ require xCAT::InstUtils; require xCAT::NetworkUtils; require xCAT::Schema; require xCAT::Utils; +require xCAT::TableUtils; #use Data::Dumper; require xCAT::NodeRange; use xCAT::MsgUtils qw(verbose_message); @@ -130,7 +131,7 @@ sub getIPaddress my $type = shift; my $nodetocheck = shift; my $port = shift; - if (xCAT::Utils::isIpaddr($nodetocheck)) { + if (xCAT::NetworkUtils::isIpaddr($nodetocheck)) { return $nodetocheck; } my $side = "[A|B]"; @@ -188,7 +189,7 @@ sub getIPaddress if ($tmp_s and $tmp_s =~ /^$side-$port$/i) { $tmp_s =~ s/a/A/; $tmp_s =~ s/b/B/; - if (xCAT::Utils::isIpaddr($tmp_n)) { + if (xCAT::NetworkUtils::isIpaddr($tmp_n)) { $node_side_pairs{$tmp_s} = $tmp_n; $children_num++; } else { @@ -346,7 +347,7 @@ sub fsp_api_action { } my $cmd; - my $install_dir = xCAT::Utils->getInstallDir(); + my $install_dir = xCAT::TableUtils->getInstallDir(); if( $action =~ /^(code_update|get_compatible_version_from_rpm)$/) { $cmd = "$fsp_api -a $action -T $tooltype -t $type:$fsp_ip:$id:$node_name:$parameter -d $install_dir/packages_fw/"; } elsif($action =~ /^code_updateD$/) { diff --git a/perl-xCAT/xCAT/FSPcfg.pm b/perl-xCAT/xCAT/FSPcfg.pm index 124b06238..dbefb0831 100644 --- a/perl-xCAT/xCAT/FSPcfg.pm +++ b/perl-xCAT/xCAT/FSPcfg.pm @@ -6,6 +6,7 @@ use Getopt::Long; use xCAT::Usage; use xCAT::Utils; use xCAT::FSPUtils; +use xCAT::TableUtils; use xCAT::PPCcfg; #use Data::Dumper; #use xCAT::PPCcli; @@ -224,7 +225,7 @@ sub parse_args { my $ppc_cmds_string = &array_to_string(\@ppc_cmds); return (usage("Invalid command array: $fsp_cmds_string can not execute with $ppc_cmds_string.")); } elsif(scalar(@ppc_cmds)) { - my @enableASMI = xCAT::Utils->get_site_attribute("enableASMI"); + my @enableASMI = xCAT::TableUtils->get_site_attribute("enableASMI"); if (defined($enableASMI[0])) { $enableASMI[0] =~ tr/a-z/A-Z/; # convert to upper if (($enableASMI[0] eq "1") || ($enableASMI[0] eq "YES")) { @@ -871,8 +872,8 @@ sub fsp_api_passwd { ############################ # Get IP address ############################ - #$fsp_ip = xCAT::Utils::get_hdwr_ip($fsp_name); - #$fsp_ip = xCAT::Utils::getNodeIPaddress($fsp_name); + #$fsp_ip = xCAT::NetworkUtils::get_hdwr_ip($fsp_name); + #$fsp_ip = xCAT::NetworkUtils::getNodeIPaddress($fsp_name); #$fsp_ip = xCAT::Utils::getIPaddress($fsp_name); $fsp_ip = xCAT::FSPUtils::getIPaddress($request, $$attrs[4], $fsp_name ); if(!defined($fsp_ip) or ($fsp_ip == -3)) { diff --git a/perl-xCAT/xCAT/InstUtils.pm b/perl-xCAT/xCAT/InstUtils.pm index 018bfe6d8..a1fc58201 100644 --- a/perl-xCAT/xCAT/InstUtils.pm +++ b/perl-xCAT/xCAT/InstUtils.pm @@ -23,7 +23,7 @@ use File::Path; use strict; require xCAT::Schema; use xCAT::NetworkUtils; - +use xCAT::TableUtils; #require Data::Dumper; #use Data::Dumper; require xCAT::NodeRange; @@ -67,10 +67,10 @@ sub getnimprime # the primary NIM master is either specified in the site table # or it is the xCAT management node. - my $nimprime = xCAT::Utils->get_site_Master(); + my $nimprime = xCAT::TableUtils->get_site_Master(); #my $sitetab = xCAT::Table->new('site'); #(my $et) = $sitetab->getAttribs({key => "nimprime"}, 'value'); - my @nimprimes = xCAT::Utils->get_site_attribute("nimprime"); + my @nimprimes = xCAT::TableUtils->get_site_attribute("nimprime"); my $tmp = $nimprimes[0]; if (defined($tmp)) { @@ -126,7 +126,7 @@ sub myxCATname if (xCAT::Utils->isMN()) { # read the site table, master attrib - my $hostname = xCAT::Utils->get_site_Master(); + my $hostname = xCAT::TableUtils->get_site_Master(); if (($hostname =~ /\d+\.\d+\.\d+\.\d+/) || ($hostname =~ /:/)) { $name = xCAT::NetworkUtils->gethostname($hostname); @@ -750,11 +750,11 @@ sub get_server_nodes else { # get ip facing node - $serv = xCAT::Utils->my_ip_facing($node); + $serv = xCAT::NetworkUtils->my_ip_facing($node); } chomp $serv; - if (xCAT::Utils->validate_ip($serv)) { + if (xCAT::NetworkUtils->validate_ip($serv)) { push (@{$servernodes{$serv}}, $node); } } @@ -1253,7 +1253,7 @@ sub dolitesetup # add aixlitesetup to ..inst_root/aixlitesetup # this will wind up in the root dir on the node ("/") - my $install_dir = xCAT::Utils->getInstallDir(); + my $install_dir = xCAT::TableUtils->getInstallDir(); my $cpcmd = "/bin/cp $install_dir/postscripts/aixlitesetup $instrootloc/aixlitesetup; chmod +x $instrootloc/aixlitesetup"; my $out = xCAT::Utils->runcmd("$cpcmd", -1); diff --git a/perl-xCAT/xCAT/MacMap.pm b/perl-xCAT/xCAT/MacMap.pm index cfe643b47..85044b908 100644 --- a/perl-xCAT/xCAT/MacMap.pm +++ b/perl-xCAT/xCAT/MacMap.pm @@ -8,6 +8,7 @@ use strict; use xCAT::Table; use xCAT::Utils; use xCAT::MsgUtils; +use xCAT::TableUtils; use IO::Select; use IO::Handle; use Sys::Syslog; @@ -167,7 +168,7 @@ sub rvlan { my $community = "public"; #$self->{sitetab} = xCAT::Table->new('site'); #my $tmp = $self->{sitetab}->getAttribs({key=>'snmpc'},'value'); - my @snmpcs = xCAT::Utils->get_site_attribute("snmpc"); + my @snmpcs = xCAT::TableUtils->get_site_attribute("snmpc"); my $tmp = $snmpcs[0]; if ( defined($tmp) ) { $community = $tmp } my %args = @_; @@ -292,7 +293,7 @@ sub refresh_table { #$self->{sitetab} = xCAT::Table->new('site'); #my $tmp = $self->{sitetab}->getAttribs({key=>'snmpc'},'value'); #if ($tmp and $tmp->{value}) { $community = $tmp->{value} } - my @snmpcs = xCAT::Utils->get_site_attribute("snmpc"); + my @snmpcs = xCAT::TableUtils->get_site_attribute("snmpc"); my $tmp = $snmpcs[0]; if ( defined($tmp) ) { $community = $tmp } else { #Would warn here.. diff --git a/perl-xCAT/xCAT/NetworkUtils.pm b/perl-xCAT/xCAT/NetworkUtils.pm index cd4e0822d..c02eb4d93 100755 --- a/perl-xCAT/xCAT/NetworkUtils.pm +++ b/perl-xCAT/xCAT/NetworkUtils.pm @@ -25,7 +25,7 @@ my $socket6support = eval { require Socket6 }; our @ISA = qw(Exporter); our @EXPORT_OK = qw(getipaddr); - +my $utildata; #data to persist locally #-------------------------------------------------------------------------------- =head1 xCAT::NetworkUtils @@ -481,9 +481,9 @@ sub my_ip_in_subnet return undef; } - my $fmask = xCAT::Utils::formatNetmask($mask, 0, 1); + my $fmask = xCAT::NetworkUtils::formatNetmask($mask, 0, 1); - my $localnets = xCAT::Utils->my_nets(); + my $localnets = xCAT::NetworkUtils->my_nets(); return $localnets->{"$net\/$fmask"}; } @@ -623,4 +623,1349 @@ sub get_nic_ip } return \%iphash; } + +#------------------------------------------------------------------------------- + +=head3 classful_networks_for_net_and_mask + + Arguments: + network and mask + Returns: + a list of classful subnets that constitute the entire potentially classless arguments + Globals: + none + Error: + none + Example: + Comments: + none +=cut + +#------------------------------------------------------------------------------- +sub classful_networks_for_net_and_mask +{ + my $network = shift; + my $mask = shift; + my $given_mask = 0; + if ($mask =~ /\./) + { + $given_mask = 1; + my $masknumber = unpack("N", inet_aton($mask)); + $mask = 32; + until ($masknumber % 2) + { + $masknumber = $masknumber >> 1; + $mask--; + } + } + + my @results; + my $bitstoeven = (8 - ($mask % 8)); + if ($bitstoeven eq 8) { $bitstoeven = 0; } + my $resultmask = $mask + $bitstoeven; + if ($given_mask) + { + $resultmask = + inet_ntoa(pack("N", (2**$resultmask - 1) << (32 - $resultmask))); + } + push @results, $resultmask; + + my $padbits = (32 - ($bitstoeven + $mask)); + my $numchars = int(($mask + $bitstoeven) / 4); + my $curmask = 2**$mask - 1 << (32 - $mask); + my $nown = unpack("N", inet_aton($network)); + $nown = $nown & $curmask; + my $highn = $nown + ((2**$bitstoeven - 1) << (32 - $mask - $bitstoeven)); + + while ($nown <= $highn) + { + push @results, inet_ntoa(pack("N", $nown)); + + #$rethash->{substr($nowhex, 0, $numchars)} = $network; + $nown += 1 << (32 - $mask - $bitstoeven); + } + return @results; +} + + +#------------------------------------------------------------------------------- + +=head3 my_hexnets + + Arguments: + none + Returns: + Globals: + none + Error: + none + Example: + Comments: + none +=cut + +#------------------------------------------------------------------------------- +sub my_hexnets +{ + my $rethash; + my @nets = split /\n/, `/sbin/ip addr`; + foreach (@nets) + { + my @elems = split /\s+/; + unless (/^\s*inet\s/) + { + next; + } + (my $curnet, my $maskbits) = split /\//, $elems[2]; + my $bitstoeven = (4 - ($maskbits % 4)); + if ($bitstoeven eq 4) { $bitstoeven = 0; } + my $padbits = (32 - ($bitstoeven + $maskbits)); + my $numchars = int(($maskbits + $bitstoeven) / 4); + my $curmask = 2**$maskbits - 1 << (32 - $maskbits); + my $nown = unpack("N", inet_aton($curnet)); + $nown = $nown & $curmask; + my $highn = + $nown + ((2**$bitstoeven - 1) << (32 - $maskbits - $bitstoeven)); + + while ($nown <= $highn) + { + my $nowhex = sprintf("%08x", $nown); + $rethash->{substr($nowhex, 0, $numchars)} = $curnet; + $nown += 1 << (32 - $maskbits - $bitstoeven); + } + } + return $rethash; +} + +#------------------------------------------------------------------------------- + +=head3 get_host_from_ip + Description: + Get the hostname of an IP addresses. First from hosts table, and then try system resultion. + If there is a shortname, it will be returned. Otherwise it will return long name. If the IP cannot be resolved, return undef; + + Arguments: + $ip: the IP to get; + + Returns: + Return: the hostname. +For an example + + Globals: + none + + Error: + none + + Example: + xCAT::NetworkUtils::get_host_from_ip('192.168.200.1') + + Comments: +=cut + +#----------------------------------------------------------------------- +sub get_host_from_ip +{ + my $ip = shift; +} + +#------------------------------------------------------------------------------- + +=head3 isPingable + Description: + Check if an IP address can be pinged + + Arguments: + $ip: the IP to ping; + + Returns: + Return: 1 indicates yes; 0 indicates no. +For an example + + Globals: + none + + Error: + none + + Example: + xCAT::NetworkUtils::isPingable('192.168.200.1') + + Comments: + none +=cut + +#----------------------------------------------------------------------- +my %PING_CACHE; +sub isPingable +{ + my $ip = shift; + + my $rc; + if ( exists $PING_CACHE{ $ip}) + { + $rc = $PING_CACHE{ $ip}; + } + else + { + my $res = `LANG=C ping -c 1 -w 5 $ip 2>&1`; + if ( $res =~ /100% packet loss/g) + { + $rc = 1; + } + else + { + $rc = 0; + } + $PING_CACHE{ $ip} = $rc; + } + + return ! $rc; +} + +#------------------------------------------------------------------------------- + +=head3 my_nets + Description: + Return a hash ref that contains all subnet and netmask on the mn (or sn). This subroutine can be invoked on both Linux and AIX. + + Arguments: + none. + + Returns: + Return a hash ref. Each entry will be: =>; + For an example: + '192.168.200.0/255.255.255.0' => '192.168.200.246'; +For an example + + Globals: + none + + Error: + none + + Example: + xCAT::NetworkUtils::my_nets(). + + Comments: + none +=cut +#----------------------------------------------------------------------- +sub my_nets +{ + require xCAT::Table; + my $rethash; + my @nets; + my $v6net; + my $v6ip; + if ( $^O eq 'aix') + { + @nets = split /\n/, `/usr/sbin/ifconfig -a`; + } + else + { + @nets = split /\n/, `/sbin/ip addr`; #could use ip route, but to match hexnets... + } + foreach (@nets) + { + $v6net = ''; + my @elems = split /\s+/; + unless (/^\s*inet/) + { + next; + } + my $curnet; my $maskbits; + if ( $^O eq 'aix') + { + if ($elems[1] eq 'inet6') + { + $v6net=$elems[2]; + $v6ip=$elems[2]; + $v6ip =~ s/\/.*//; # ipv6 address 4000::99/64 + $v6ip =~ s/\%.*//; # ipv6 address ::1%1/128 + } + else + { + $curnet = $elems[2]; + $maskbits = formatNetmask( $elems[4], 2, 1); + } + } + else + { + if ($elems[1] eq 'inet6') + { + next; #Linux IPv6 TODO, do not return IPv6 networks on Linux for now + } + ($curnet, $maskbits) = split /\//, $elems[2]; + } + if (!$v6net) + { + my $curmask = 2**$maskbits - 1 << (32 - $maskbits); + my $nown = unpack("N", inet_aton($curnet)); + $nown = $nown & $curmask; + my $textnet=inet_ntoa(pack("N",$nown)); + $textnet.="/$maskbits"; + $rethash->{$textnet} = $curnet; + } + else + { + $rethash->{$v6net} = $v6ip; + } + } + + + # now get remote nets + my $nettab = xCAT::Table->new("networks"); + #my $sitetab = xCAT::Table->new("site"); + #my $master = $sitetab->getAttribs({key=>'master'},'value'); + #$master = $master->{value}; + my @masters = xCAT::TableUtils->get_site_attribute("master"); + my $master = $masters[0]; + my @vnets = $nettab->getAllAttribs('net','mgtifname','mask'); + + foreach(@vnets){ + my $n = $_->{net}; + my $if = $_->{mgtifname}; + my $nm = $_->{mask}; + if (!$n || !$if || $nm) + { + next; #incomplete network + } + if ($if =~ /!remote!/) { #only take in networks with special interface + $nm = formatNetmask($nm, 0 , 1); + $n .="/$nm"; + #$rethash->{$n} = $if; + $rethash->{$n} = $master; + } + } + return $rethash; +} +#------------------------------------------------------------------------------- + +=head3 my_if_netmap + Arguments: + none + Returns: + hash of networks to interface names + Globals: + none + Error: + none + Comments: + none +=cut + +#------------------------------------------------------------------------------- +sub my_if_netmap +{ + my $net; + if (scalar(@_)) + { #called with the other syntax + $net = shift; + } + my @rtable = split /\n/, `netstat -rn`; + if ($?) + { + return "Unable to run netstat, $?"; + } + my %retmap; + foreach (@rtable) + { + if (/^\D/) { next; } #skip headers + if (/^\S+\s+\S+\s+\S+\s+\S*G/) + { + next; + } #Skip networks that require gateways to get to + /^(\S+)\s.*\s(\S+)$/; + $retmap{$1} = $2; + } + return \%retmap; +} + +#------------------------------------------------------------------------------- + +=head3 my_ip_facing + Returns my ip address + Linux only + Arguments: + nodename + Returns: + Globals: + none + Error: + none + Example: + Comments: + none +=cut + +#------------------------------------------------------------------------------- +sub my_ip_facing +{ + my $peer = shift; + if (@_) + { + $peer = shift; + } + return my_ip_facing_aix( $peer) if ( $^O eq 'aix'); + my $peernumber = inet_aton($peer); #TODO: IPv6 support + unless ($peernumber) { return undef; } + my $noden = unpack("N", inet_aton($peer)); + my @nets = split /\n/, `/sbin/ip addr`; + foreach (@nets) + { + my @elems = split /\s+/; + unless (/^\s*inet\s/) + { + next; + } + (my $curnet, my $maskbits) = split /\//, $elems[2]; + my $curmask = 2**$maskbits - 1 << (32 - $maskbits); + my $curn = unpack("N", inet_aton($curnet)); + if (($noden & $curmask) == ($curn & $curmask)) + { + return $curnet; + } + } + return undef; +} + +#------------------------------------------------------------------------------- + +=head3 my_ip_facing_aix + Returns my ip address + AIX only + Arguments: + nodename + Returns: + Globals: + none + Error: + none + Example: + Comments: + none +=cut + +#------------------------------------------------------------------------------- +sub my_ip_facing_aix +{ + my $peer = shift; + my @nets = `ifconfig -a`; + chomp @nets; + foreach my $net (@nets) + { + my ($curnet,$netmask); + if ( $net =~ /^\s*inet\s+([\d\.]+)\s+netmask\s+(\w+)\s+broadcast/) + { + ($curnet,$netmask) = ($1,$2); + } + elsif ($net =~ /^\s*inet6\s+(.*)$/) + { + ($curnet,$netmask) = split('/', $1); + } + else + { + next; + } + if (isInSameSubnet($peer, $curnet, $netmask, 2)) + { + return $curnet; + } + } + return undef; +} + +#------------------------------------------------------------------------------- + +=head3 formatNetmask + Description: + Transform netmask to one of 3 formats (255.255.255.0, 24, 0xffffff00). + + Arguments: + $netmask: the original netmask + $origType: the original netmask type. The valid value can be 0, 1, 2: + Type 0: 255.255.255.0 + Type 1: 24 + Type 2: 0xffffff00 + $newType: the new netmask type, valid values can be 0,1,2, as above. + + Returns: + Return undef if any error. Otherwise return the netmask in new format. + + Globals: + none + + Error: + none + + Example: + xCAT::NetworkUtils::formatNetmask( '24', 1, 0); #return '255.255.255.0'. + + Comments: + none +=cut +#----------------------------------------------------------------------- +sub formatNetmask +{ + my $mask = shift; + my $origType = shift; + my $newType = shift; + my $maskn; + if ( $origType == 0) + { + $maskn = unpack("N", inet_aton($mask)); + } + elsif ( $origType == 1) + { + $maskn = 2**$mask - 1 << (32 - $mask); + } + elsif( $origType == 2) + { + $maskn = hex $mask; + } + else + { + return undef; + } + + if ( $newType == 0) + { + return inet_ntoa( pack('N', $maskn)); + } + if ( $newType == 1) + { + my $bin = unpack ("B32", pack("N", $maskn)); + my @dup = ( $bin =~ /(1{1})0*/g); + return scalar ( @dup); + } + if ( $newType == 2) + { + return sprintf "0x%1x", $maskn; + } + return undef; +} + +#------------------------------------------------------------------------------- + +=head3 isInSameSubnet + Description: + Check if 2 given IP addresses are in same subnet + + Arguments: + $ip1: the first IP + $ip2: the second IP + $mask: the netmask, here are 3 possible netmask types, following are examples for these 3 types: + Type 0: 255.255.255.0 + Type 1: 24 + Type 2: 0xffffff00 + $masktype: the netmask type, 3 possible values: 0,1,2, as indicated above + + Returns: + 1: they are in same subnet + 2: not in same subnet + + Globals: + none + + Error: + none + + Example: + xCAT::NetworkUtils::isInSameSubnet( '192.168.10.1', '192.168.10.2', '255.255.255.0', 0); + + Comments: + none +=cut +#----------------------------------------------------------------------- +sub isInSameSubnet +{ + my $ip1 = shift; + my $ip2 = shift; + my $mask = shift; + my $maskType = shift; + + $ip1 = xCAT::NetworkUtils->getipaddr($ip1); + $ip2 = xCAT::NetworkUtils->getipaddr($ip2); + + if (!defined($ip1) || !defined($ip2)) + { + return undef; + } + + if ((($ip1 =~ /\d+\.\d+\.\d+\.\d+/) && ($ip2 !~ /\d+\.\d+\.\d+\.\d+/)) + ||(($ip1 !~ /\d+\.\d+\.\d+\.\d+/) && ($ip2 =~ /\d+\.\d+\.\d+\.\d+/))) + { + #ipv4 and ipv6 can not be in the same subnet + return undef; + } + + if (($ip1 =~ /\d+\.\d+\.\d+\.\d+/) && ($ip2 =~ /\d+\.\d+\.\d+\.\d+/)) + { + my $maskn; + if ( $maskType == 0) + { + $maskn = unpack("N", inet_aton($mask)); + } + elsif ( $maskType == 1) + { + $maskn = 2**$mask - 1 << (32 - $mask); + } + elsif( $maskType == 2) + { + $maskn = hex $mask; + } + else + { + return undef; + } + + my $ip1n = unpack("N", inet_aton($ip1)); + my $ip2n = unpack("N", inet_aton($ip2)); + + return ( ( $ip1n & $maskn) == ( $ip2n & $maskn) ); + } + else + { + #ipv6 + if (($ip1 =~ /\%/) || ($ip2 =~ /\%/)) + { + return undef; + } + my $netipmodule = eval {require Net::IP;}; + if ($netipmodule) { + my $eip1 = Net::IP::ip_expand_address ($ip1,6); + my $eip2 = Net::IP::ip_expand_address ($ip2,6); + my $bmask = Net::IP::ip_get_mask($mask,6); + my $bip1 = Net::IP::ip_iptobin($eip1,6); + my $bip2 = Net::IP::ip_iptobin($eip2,6); + if (($bip1 & $bmask) == ($bip2 & $bmask)) { + return 1; + } + } # else, can not check without Net::IP module + return undef; + } +} +#------------------------------------------------------------------------------- + +=head3 nodeonmynet - checks to see if node is on any network this server is attached to or remote network potentially managed by this system + Arguments: + Node name + Returns: 1 if node is on the network + Globals: + none + Error: + none + Example: + Comments: + none +=cut + +#------------------------------------------------------------------------------- + +sub nodeonmynet +{ + require xCAT::Table; + my $nodetocheck = shift; + if (scalar(@_)) + { + $nodetocheck = shift; + } + + my $nodeip = getNodeIPaddress( $nodetocheck ); + if (!$nodeip) + { + return 0; + } + unless ($nodeip =~ /\d+\.\d+\.\d+\.\d+/) + { + #IPv6 + if ( $^O eq 'aix') + { + my @subnets = get_subnet_aix(); + for my $net_ent (@subnets) + { + if ($net_ent !~ /-/) + { + #ipv4 + next; + } + my ($net, $interface, $mask, $flag) = split/-/ , $net_ent; + if (xCAT::NetworkUtils->ishostinsubnet($nodeip, $mask, $net)) + { + return 1; + } + } + + } else { + my @v6routes = split /\n/,`ip -6 route`; + foreach (@v6routes) { + if (/via/ or /^unreachable/ or /^fe80::\/64/) { + #only count local ones, remote ones can be caught in next loop + #also, link-local would be a pitfall, + #since more context than address is + #needed to determine locality + next; + } + s/ .*//; #remove all after the space + if (xCAT::NetworkUtils->ishostinsubnet($nodeip,'',$_)) { #bank on CIDR support + return 1; + } + } + } + my $nettab=xCAT::Table->new("networks"); + my @vnets = $nettab->getAllAttribs('net','mgtifname','mask'); + foreach (@vnets) { + if ((defined $_->{mgtifname}) && ($_->{mgtifname} eq '!remote!')) + { + if (xCAT::NetworkUtils->ishostinsubnet($nodeip, $_->{mask}, $_->{net})) + { + return 1; + } + } + } + return 0; + } + my $noden = unpack("N", inet_aton($nodeip)); + my @nets; + if ($utildata->{nodeonmynetdata} and $utildata->{nodeonmynetdata}->{pid} == $$) { + @nets = @{$utildata->{nodeonmynetdata}->{nets}}; + } else { + if ( $^O eq 'aix') + { + my @subnets = get_subnet_aix(); + for my $net_ent (@subnets) + { + if ($net_ent =~ /-/) + { + #ipv6 + next; + } + my @ents = split /:/ , $net_ent; + push @nets, $ents[0] . '/' . $ents[2] . ' dev ' . $ents[1]; + } + + } + else + { + @nets = split /\n/, `/sbin/ip route`; + } + my $nettab=xCAT::Table->new("networks"); + my @vnets = $nettab->getAllAttribs('net','mgtifname','mask'); + foreach (@vnets) { + if ((defined $_->{mgtifname}) && ($_->{mgtifname} eq '!remote!')) + { #global scoped network + my $curm = unpack("N", inet_aton($_->{mask})); + my $bits=32; + until ($curm & 1) { + $bits--; + $curm=$curm>>1; + } + push @nets,$_->{'net'}."/".$bits." dev remote"; + } + } + $utildata->{nodeonmynetdata}->{pid}=$$; + $utildata->{nodeonmynetdata}->{nets} = \@nets; + } + foreach (@nets) + { + my @elems = split /\s+/; + unless ($elems[1] =~ /dev/) + { + next; + } + (my $curnet, my $maskbits) = split /\//, $elems[0]; + my $curmask = 2**$maskbits - 1 << (32 - $maskbits); + my $curn = unpack("N", inet_aton($curnet)); + if (($noden & $curmask) == $curn) + { + return 1; + } + } + return 0; +} + +#------------------------------------------------------------------------------- + +=head3 getNodeIPaddress + Arguments: + Node name only one at a time + Returns: ip address(s) + Globals: + none + Error: + none + Example: my $c1 = xCAT::NetworkUtils::getNodeIPaddress($nodetocheck); + +=cut + +#------------------------------------------------------------------------------- + +sub getNodeIPaddress +{ + require xCAT::Table; + my $nodetocheck = shift; + my $port = shift; + my $nodeip; + + $nodeip = xCAT::NetworkUtils->getipaddr($nodetocheck); + if (!$nodeip) + { + my $hoststab = xCAT::Table->new( 'hosts'); + my $ent = $hoststab->getNodeAttribs( $nodetocheck, ['ip'] ); + if ( $ent->{'ip'} ) { + $nodeip = $ent->{'ip'}; + } + } + + if ( $nodeip ) { + return $nodeip; + } else { + return undef; + } +} + + + +#------------------------------------------------------------------------------- + +=head3 thishostisnot + returns 0 if host is not the same + Arguments: + hostname + Returns: + Globals: + none + Error: + none + Example: + Comments: + none +=cut + +#------------------------------------------------------------------------------- + +sub thishostisnot +{ + my $comparison = shift; + if (scalar(@_)) + { + $comparison = shift; + } + + my @ips; + if ( $^O eq 'aix') + { + @ips = split /\n/, `/usr/sbin/ifconfig -a`; + } + else + { + @ips = split /\n/, `/sbin/ip addr`; + } + my $comp = xCAT::NetworkUtils->getipaddr($comparison); + if ($comp) + { + foreach (@ips) + { + if (/^\s*inet.?\s+/) + { + my @ents = split(/\s+/); + my $ip = $ents[2]; + $ip =~ s/\/.*//; + $ip =~ s/\%.*//; + if ($ip eq $comp) + { + return 0; + } + } + } + } + return 1; +} + +#----------------------------------------------------------------------------- + +=head3 gethost_ips (AIX and Linux) + Will use ifconfig to determine all possible ip addresses for the + host it is running on and then gethostbyaddr to get all possible hostnames + + input: + output: array of ipaddress(s) and hostnames + example: @ips=xCAT::NetworkUtils->gethost_ips(); + +=cut + +#----------------------------------------------------------------------------- +sub gethost_ips +{ + my ($class) = @_; + my $cmd; + my @ipaddress; + $cmd = "ifconfig" . " -a"; + $cmd = $cmd . "| grep \"inet\""; + my @result = xCAT::Utils->runcmd($cmd, 0); + if ($::RUNCMD_RC != 0) + { + xCAT::MsgUtils->message("S", "Error from $cmd\n"); + exit $::RUNCMD_RC; + } + foreach my $addr (@result) + { + my @ip; + if (xCAT::Utils->isLinux()) + { + if ($addr =~ /inet6/) + { + #TODO, Linux ipv6 + } + else + { + my ($inet, $addr1, $Bcast, $Mask) = split(" ", $addr); + @ip = split(":", $addr1); + push @ipaddress, $ip[1]; + } + } + else + { #AIX + if ($addr =~ /inet6/) + { + $addr =~ /\s*inet6\s+([\da-fA-F:]+).*\/(\d+)/; + my $v6ip = $1; + my $v6mask = $2; + if ($v6ip) + { + push @ipaddress, $v6ip; + } + } + else + { + my ($inet, $addr1, $netmask, $mask1, $Bcast, $bcastaddr) = + split(" ", $addr); + push @ipaddress, $addr1; + } + + } + } + my @names = @ipaddress; + foreach my $ipaddr (@names) + { + my $hostname = xCAT::NetworkUtils->gethostname($ipaddr); + if ($hostname) + { + my @shorthost = split(/\./, $hostname); + push @ipaddress, $shorthost[0]; + } + } + + return @ipaddress; +} +#------------------------------------------------------------------------------- + +=head3 get_subnet_aix + Description: + To get present subnet configuration by parsing the output of 'netstat'. Only designed for AIX. + Arguments: + None + Returns: + @aix_nrn : An array with entries in format "net:nic:netmask:flag". Following is an example entry: + 9.114.47.224:en0:27:U + Globals: + none + Error: + none + Example: + my @nrn =xCAT::NetworkUtils::get_subnet_aix + Comments: + none + +=cut + +#------------------------------------------------------------------------------- +sub get_subnet_aix +{ + my @netstat_res = `/usr/bin/netstat -rn`; + chomp @netstat_res; + my @aix_nrn; + for my $entry ( @netstat_res) + { +#We need to find entries like: +#Destination Gateway Flags Refs Use If Exp Groups +#9.114.47.192/27 9.114.47.205 U 1 1 en0 +#4000::/64 link#4 UCX 1 0 en2 - - + my ( $net, $netmask, $flag, $nic); + if ( $entry =~ /^\s*([\d\.]+)\/(\d+)\s+[\d\.]+\s+(\w+)\s+\d+\s+\d+\s(\w+)/) + { + ( $net, $netmask, $flag, $nic) = ($1,$2,$3,$4); + my @dotsec = split /\./, $net; + for ( my $i = 4; $i > scalar(@dotsec); $i--) + { + $net .= '.0'; + } + push @aix_nrn, "$net:$nic:$netmask:$flag" if ($net ne '127.0.0.0'); + } + elsif ($entry =~ /^\s*([\dA-Fa-f\:]+)\/(\d+)\s+.*?\s+(\w+)\s+\d+\s+\d+\s(\w+)/) + { + #print "=====$entry====\n"; + ( $net, $netmask, $flag, $nic) = ($1,$2,$3,$4); + # for ipv6, can not use : as the delimiter + push @aix_nrn, "$net-$nic-$netmask-$flag" if ($net ne '::') + } + } + return @aix_nrn; +} + +#----------------------------------------------------------------------------- + +=head3 determinehostname and ip address(s) + + Used on the service node to figure out what hostname and ip address(s) + are valid names and addresses + Input: None + Output: ipaddress(s),nodename +=cut + +#----------------------------------------------------------------------------- +sub determinehostname +{ + my $hostname; + my $hostnamecmd = "/bin/hostname"; + my @thostname = xCAT::Utils->runcmd($hostnamecmd, 0); + if ($::RUNCMD_RC != 0) + { # could not get hostname + xCAT::MsgUtils->message("S", + "Error $::RUNCMD_RC from $hostnamecmd command\n"); + exit $::RUNCMD_RC; + } + $hostname = $thostname[0]; + + #get all potentially valid abbreviations, and pick the one that is ok + #by 'noderange' + my @hostnamecandidates; + my $nodename; + while ($hostname =~ /\./) { + push @hostnamecandidates,$hostname; + $hostname =~ s/\.[^\.]*//; + } + push @hostnamecandidates,$hostname; + my $checkhostnames = join(',',@hostnamecandidates); + my @validnodenames = xCAT::NodeRange::noderange($checkhostnames); + unless (scalar @validnodenames) { #If the node in question is not in table, take output literrally. + push @validnodenames,$hostnamecandidates[0]; + } + #now, noderange doesn't guarantee the order, so we search the preference order, most to least specific. + foreach my $host (@hostnamecandidates) { + if (grep /^$host$/,@validnodenames) { + $nodename = $host; + last; + } + } + my @ips = xCAT::NetworkUtils->gethost_ips; + my @hostinfo = (@ips, $nodename); + + return @hostinfo; +} + +#----------------------------------------------------------------------------- + +=head3 toIP + + IPv4 function to convert hostname to IP address + +=cut + +#----------------------------------------------------------------------------- +sub toIP +{ + + if (($_[0] =~ /^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$/) || ($_[0] =~ /:/)) + { + return ([0, $_[0]]); + } + my $ip = xCAT::NetworkUtils->getipaddr($_[0]); + if (!$ip) + { + return ([1, "Cannot Resolve: $_[0]\n"]); + } + return ([0, $ip]); +} + +#------------------------------------------------------------------------------- + +=head3 validate_ip + Validate list of IPs + Arguments: + List of IPs + Returns: + 1 - Invalid IP address in the list + 0 - IP addresses are all valid + Globals: + none + Error: + none + Example: + if (xCAT::NetworkUtils->validate_ip($IP)) {} + Comments: + none +=cut + +#------------------------------------------------------------------------------- +sub validate_ip +{ + my ($class, @IPs) = @_; + foreach (@IPs) { + my $ip = $_; + #TODO need more check for IPv6 address + if ($ip =~ /:/) + { + return([0]); + } + ################################### + # Length is 4 for IPv4 addresses + ################################### + my (@octets) = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/; + if ( scalar(@octets) != 4 ) { + return( [1,"Invalid IP address1: $ip"] ); + } + foreach my $octet ( @octets ) { + if (( $octet < 0 ) or ( $octet > 255 )) { + return( [1,"Invalid IP address2: $ip"] ); + } + } + } + return([0]); +} + +#------------------------------------------------------------------------------- + +=head3 getFacingIP + Gets the ip address of the adapter of the localhost that is facing the + the given node. + Assume it is the same as my_ip_facing... + Arguments: + The name of the node that is facing the localhost. + Returns: + The ip address of the adapter that faces the node. + +=cut + +#------------------------------------------------------------------------------- +sub getFacingIP +{ + my ($class, $node) = @_; + my $ip; + my $cmd; + my @ipaddress; + + my $nodeip = inet_ntoa(inet_aton($node)); + unless ($nodeip =~ /\d+\.\d+\.\d+\.\d+/) + { + return 0; #Not supporting IPv6 here IPV6TODO + } + + $cmd = "ifconfig" . " -a"; + $cmd = $cmd . "| grep \"inet \""; + my @result = xCAT::Utils->runcmd($cmd, 0); + if ($::RUNCMD_RC != 0) + { + xCAT::MsgUtils->message("S", "Error from $cmd\n"); + exit $::RUNCMD_RC; + } + + # split node address + my ($n1, $n2, $n3, $n4) = split('\.', $nodeip); + + foreach my $addr (@result) + { + my $ip; + my $mask; + if (xCAT::Utils->isLinux()) + { + my ($inet, $addr1, $Bcast, $Mask) = split(" ", $addr); + if ((!$addr1) || (!$Mask)) { next; } + my @ips = split(":", $addr1); + my @masks = split(":", $Mask); + $ip = $ips[1]; + $mask = $masks[1]; + } + else + { #AIX + my ($inet, $addr1, $netmask, $mask1, $Bcast, $bcastaddr) = + split(" ", $addr); + if ((!$addr1) && (!$mask1)) { next; } + $ip = $addr1; + $mask1 =~ s/0x//; + $mask = + `printf "%d.%d.%d.%d" \$(echo "$mask1" | sed 's/../0x& /g')`; + } + + if ($ip && $mask) + { + + # split interface IP + my ($h1, $h2, $h3, $h4) = split('\.', $ip); + + # split mask + my ($m1, $m2, $m3, $m4) = split('\.', $mask); + + # AND this interface IP with the netmask of the network + my $a1 = ((int $h1) & (int $m1)); + my $a2 = ((int $h2) & (int $m2)); + my $a3 = ((int $h3) & (int $m3)); + my $a4 = ((int $h4) & (int $m4)); + + # AND node IP with the netmask of the network + my $b1 = ((int $n1) & (int $m1)); + my $b2 = ((int $n2) & (int $m2)); + my $b3 = ((int $n3) & (int $m3)); + my $b4 = ((int $n4) & (int $m4)); + + if (($b1 == $a1) && ($b2 == $a2) && ($b3 == $a3) && ($b4 == $a4)) + { + return $ip; + } + } + } + + xCAT::MsgUtils->message("S", "Cannot find master for the node $node\n"); + return 0; +} + +#------------------------------------------------------------------------------- + +=head3 isIpaddr + + returns 1 if parameter is has a valid IP address form. + + Arguments: + dot qulaified IP address: e.g. 1.2.3.4 + Returns: + 1 - if legal IP address + 0 - if not legal IP address. + Globals: + none + Error: + none + Example: + if ($ipAddr) { blah; } + Comments: + Doesn't test if the IP address is on the network, + just tests its form. + +=cut + +#------------------------------------------------------------------------------- +sub isIpaddr +{ + my $addr = shift; + if (($addr) && ($addr =~ /xCAT::NetworkUtils/)) + { + $addr = shift; + } + + unless ( $addr ) + { + return 0; + } + #print "addr=$addr\n"; + if ($addr !~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/) + { + return 0; + } + + if ($1 > 255 || $1 == 0 || $2 > 255 || $3 > 255 || $4 > 255) + { + return 0; + } + else + { + return 1; + } +} + +#------------------------------------------------------------------------------- + +=head3 getNodeNetworkCfg + Description: + Get node network configuration, including "IP, hostname(the nodename),and netmask" by this node's name. + + Arguments: + node: the nodename + Returns: + Return an array, which contains (IP,hostname,gateway,netmask'). + undef - Failed to get the network configuration info + Globals: + none + Error: + none + Example: + my ($ip,$host,undef,$mask) = xCAT::NetworkUtils::getNodeNetworkCfg('node1'); + Comments: + Presently gateway is always blank. Need to be improved. + +=cut + +#------------------------------------------------------------------------------- +sub getNodeNetworkCfg +{ + my $node = shift; + + my $nets = xCAT::NetworkUtils::my_nets(); + my $ip = xCAT::NetworkUtils->getipaddr($node); + my $mask = undef; + for my $net (keys %$nets) + { + my $netname; + ($netname,$mask) = split /\//, $net; + last if ( xCAT::NetworkUtils::isInSameSubnet( $netname, $ip, $mask, 1)); + } + return ($ip, $node, undef, xCAT::NetworkUtils::formatNetmask($mask,1,0)); +} + +#------------------------------------------------------------------------------- + +=head3 get_hdwr_ip + Description: + Get hardware(CEC, BPA) IP from the hosts table, and then /etc/hosts. + + Arguments: + node: the nodename(cec, or bpa) + Returns: + Return the node IP + -1 - Failed to get the IP. + Globals: + none + Error: + none + Example: + my $ip = xCAT::NetworkUtils::get_hdwr_ip('node1'); + Comments: + Used in FSPpower FSPflash, FSPinv. + +=cut + +#------------------------------------------------------------------------------- +sub get_hdwr_ip +{ + require xCAT::Table; + my $node = shift; + my $ip = undef; + my $Rc = undef; + + my $ip_tmp_res = xCAT::NetworkUtils::toIP($node); + ($Rc, $ip) = @$ip_tmp_res; + if ( $Rc ) { + my $hosttab = xCAT::Table->new( 'hosts' ); + if ( $hosttab) { + my $node_ip_hash = $hosttab->getNodeAttribs( $node,[qw(ip)]); + $ip = $node_ip_hash->{ip}; + } + + } + + if (!$ip) { + return undef; + } + + return $ip; +} 1; diff --git a/perl-xCAT/xCAT/PPCboot.pm b/perl-xCAT/xCAT/PPCboot.pm index c930767aa..19b53e3ef 100644 --- a/perl-xCAT/xCAT/PPCboot.pm +++ b/perl-xCAT/xCAT/PPCboot.pm @@ -8,6 +8,7 @@ use Getopt::Long; use xCAT::PPCcli qw(SUCCESS EXPECT_ERROR RC_ERROR NR_ERROR); use xCAT::Usage; use xCAT::Utils; +use xCAT::TableUtils; use xCAT::MsgUtils; use xCAT::LparNetbootExp; @@ -469,7 +470,7 @@ sub rnetboot { #my $sitetab = xCAT::Table->new('site'); #my $vcon = $sitetab->getAttribs({key => "conserverondemand"}, 'value'); - my @vcons = xCAT::Utils->get_site_attribute("conserverondemand"); + my @vcons = xCAT::TableUtils->get_site_attribute("conserverondemand"); my $vcon = $vcons[0]; #if ($vcon and $vcon->{"value"} and $vcon->{"value"} eq "yes" ) { if ( defined($vcon) and $vcon eq "yes" ) { diff --git a/perl-xCAT/xCAT/PPCcfg.pm b/perl-xCAT/xCAT/PPCcfg.pm index 31bf3e56a..387db36ed 100644 --- a/perl-xCAT/xCAT/PPCcfg.pm +++ b/perl-xCAT/xCAT/PPCcfg.pm @@ -7,6 +7,7 @@ use xCAT::PPCcli qw(SUCCESS EXPECT_ERROR RC_ERROR NR_ERROR); use xCAT::Usage; use Storable qw(freeze thaw); use POSIX "WNOHANG"; +use xCAT::NetworkUtils; use xCAT::MsgUtils qw(verbose_message); use LWP; @@ -736,7 +737,7 @@ sub doresetnet { $nodetype = ( $nodetype =~ /^frame$/i ) ? "bpa" : "fsp"; if ($cnodep) { foreach my $cnode (@$cnodep) { - my $ip = xCAT::Utils::getNodeIPaddress( $cnode ); + my $ip = xCAT::NetworkUtils::getNodeIPaddress( $cnode ); my $oi = $oihash{$cnode}; if(!defined $ip) { send_msg($req, "doresetnet: can't get $cnode ip"); @@ -785,7 +786,7 @@ sub doresetnet { # this brunch is just for the xcat 2.5(or 2.5-) databse } elsif ( $nodetype =~ /^(fsp|bpa)$/ ) { foreach my $nn ( @{ $req->{node}} ) { - my $ip = xCAT::Utils::getNodeIPaddress( $nn ); + my $ip = xCAT::NetworkUtils::getNodeIPaddress( $nn ); if(!defined $ip) { send_msg($req, "doresetnet: can't get $nn ip"); next; diff --git a/perl-xCAT/xCAT/PPCcli.pm b/perl-xCAT/xCAT/PPCcli.pm index 09f3cc187..3de42e5b8 100644 --- a/perl-xCAT/xCAT/PPCcli.pm +++ b/perl-xCAT/xCAT/PPCcli.pm @@ -6,7 +6,7 @@ require Exporter; our @ISA = qw(Exporter); our @EXPORT_OK = qw(SUCCESS RC_ERROR EXPECT_ERROR NR_ERROR); use Expect; - +use xCAT::NetworkUtils; ############################################# # Removes Ctrl characters from term output @@ -1335,7 +1335,7 @@ sub getHMCcontrolIP #my @newnodes = split(/,/, $nodes_found->[0]); #$Rc = shift(@newnodes); #for my $entry (@newnodes) { - # if(xCAT::Utils->isIpaddr($entry)) { + # if(xCAT::NetworkUtils->isIpaddr($entry)) { # push @ips,$entry; # } # $ip_result = join( ",", @ips ); diff --git a/perl-xCAT/xCAT/PPCconn.pm b/perl-xCAT/xCAT/PPCconn.pm index 8f36249c7..143f05fcd 100644 --- a/perl-xCAT/xCAT/PPCconn.pm +++ b/perl-xCAT/xCAT/PPCconn.pm @@ -5,6 +5,7 @@ use strict; use Getopt::Long; use xCAT::PPCcli qw(SUCCESS EXPECT_ERROR RC_ERROR NR_ERROR); use xCAT::Usage; +use xCAT::NetworkUtils; use xCAT::DBobjUtils; use xCAT::FSPUtils; use xCAT::MsgUtils qw(verbose_message); @@ -506,8 +507,8 @@ sub mkhwconn for my $nn ( @newnodes ) { my $node_ip; - unless ( xCAT::Utils->isIpaddr($nn) ) { - $node_ip = xCAT::Utils::getNodeIPaddress( $nn ); + unless ( xCAT::NetworkUtils->isIpaddr($nn) ) { + $node_ip = xCAT::NetworkUtils::getNodeIPaddress( $nn ); } else { $node_ip = $nn; } @@ -642,7 +643,7 @@ sub lshwconn { #my $node_ip_hash = $hosttab->getNodeAttribs( $node_name,[qw(ip)]); #$node_ip = $node_ip_hash->{ip}; - #$node_ip = xCAT::Utils::getNodeIPaddress( $node_name ); + #$node_ip = xCAT::NetworkUtils::getNodeIPaddress( $node_name ); my $d = $node_hash->{$node_name}; $node_ip = xCAT::FSPUtils::getIPaddress($request, $$d[4], $node_name ); } diff --git a/perl-xCAT/xCAT/PPCdb.pm b/perl-xCAT/xCAT/PPCdb.pm index a2f6081bd..91c347005 100644 --- a/perl-xCAT/xCAT/PPCdb.pm +++ b/perl-xCAT/xCAT/PPCdb.pm @@ -4,7 +4,9 @@ package xCAT::PPCdb; use strict; use xCAT::Table; use xCAT::GlobalDef; - +use xCAT::Utils; +use xCAT::TableUtils; +use xCAT::NetworkUtils; ########################################### # Factory defaults @@ -947,7 +949,7 @@ sub get_host { ####################################### if ($ip) { - my $nets = xCAT::Utils::my_nets(); + my $nets = xCAT::NetworkUtils::my_nets(); my $avip = getip_from_iplist( $ip, $nets); #if ( !defined( $ip )) { # return undef; @@ -984,7 +986,7 @@ sub get_host { } if ( $tmpmtm eq $mtm and $tmpsn eq $sn) { - my $ifip = xCAT::Utils->isIpaddr($oldnode); + my $ifip = xCAT::NetworkUtils->isIpaddr($oldnode); if ( $ifip ) {# which means that the node is defined by the new lsslp if ( $tmpside eq $side ) {# match! which means that node is the same as the new one if ( $ip eq $tmpip ) { #which means that the ip is not changed @@ -1104,7 +1106,7 @@ sub get_host { } # not matched, use the new name - my $ifip = xCAT::Utils->isIpaddr($nodename); + my $ifip = xCAT::NetworkUtils->isIpaddr($nodename); unless ($ifip) { return $nodename; }else { @@ -1150,8 +1152,8 @@ sub getip_from_iplist for my $net ( keys %$nets) { my ($n,$m) = split /\//,$net; - if ( xCAT::Utils::isInSameSubnet( $n, $ip, $m, 1) and - xCAT::Utils::isPingable( $ip)) + if ( xCAT::NetworkUtils::isInSameSubnet( $n, $ip, $m, 1) and + xCAT::NetworkUtils::isPingable( $ip)) { return $ip; } @@ -1211,7 +1213,7 @@ sub read_from_table { @{$::OLD_DATA_CACHE{$entry->{node}}}[1] = @{$vpdhash{$entry->{node}}}[1];#sn @{$::OLD_DATA_CACHE{$entry->{node}}}[2] = @{$vpdhash{$entry->{node}}}[2];#side # find node ip address, check node name first, then check hosts table - my $ifip = xCAT::Utils->isIpaddr($entry->{node}); + my $ifip = xCAT::NetworkUtils->isIpaddr($entry->{node}); if ( $ifip ) { @{$::OLD_DATA_CACHE{$entry->{node}}}[3] = $entry->{node};#ip diff --git a/perl-xCAT/xCAT/PPCenergy.pm b/perl-xCAT/xCAT/PPCenergy.pm index 3b3b2f058..32d54287c 100644 --- a/perl-xCAT/xCAT/PPCenergy.pm +++ b/perl-xCAT/xCAT/PPCenergy.pm @@ -8,7 +8,7 @@ use xCAT::Usage; use xCAT::NodeRange; use xCAT::DBobjUtils; use xCAT::FSPUtils; - +use xCAT::TableUtils qw(get_site_Master); %::QUERY_ATTRS = ( 'savingstatus' => 1, 'dsavingstatus' => 1, @@ -251,7 +251,7 @@ sub renergy { if( !defined($fsps) ) { return ([[$node, "Failed to get the FSPs for the cec $hcphost.", -1]]); } - #my $hcp_ip = xCAT::Utils::getNodeIPaddress($hcphost); + #my $hcp_ip = xCAT::NetworkUtils::getNodeIPaddress($hcphost); my $hcp_ip = xCAT::FSPUtils::getIPaddress($request, $hw_type, $hcphost); if (!defined($hcp_ip) or ($hcp_ip == -3)) { return ([[$node, "Failed to get IP address for $hcphost.", -1]]); @@ -264,7 +264,7 @@ sub renergy { } } else { # for the case that hcp is hmc or fsp - push @hcps_ip, xCAT::Utils::getNodeIPaddress($hcphost); + push @hcps_ip, xCAT::NetworkUtils::getNodeIPaddress($hcphost); } if (!$user || !$password) { @@ -279,7 +279,7 @@ sub renergy { } $verbose = $tmpv; - my $master = xCAT::Utils->get_site_Master(); + my $master = xCAT::TableUtils->get_site_Master(); my $masterip = xCAT::NetworkUtils->getipaddr($master); if ($masterip =~ /:/) { #IPv6, needs fping6 support if (!-x '/usr/bin/fping6') diff --git a/perl-xCAT/xCAT/PPCfsp.pm b/perl-xCAT/xCAT/PPCfsp.pm index 198ef92a4..25801e98c 100644 --- a/perl-xCAT/xCAT/PPCfsp.pm +++ b/perl-xCAT/xCAT/PPCfsp.pm @@ -11,7 +11,9 @@ use xCAT::Usage; use Socket; use xCAT::PPCdb; use xCAT::MsgUtils qw(verbose_message); - +use xCAT::Utils; +use xCAT::TableUtils; +use xCAT::NetworkUtils; ########################################## # Globals ########################################## diff --git a/perl-xCAT/xCAT/PPCmac.pm b/perl-xCAT/xCAT/PPCmac.pm index 813d1e3c9..a12186903 100644 --- a/perl-xCAT/xCAT/PPCmac.pm +++ b/perl-xCAT/xCAT/PPCmac.pm @@ -6,6 +6,9 @@ use strict; use Getopt::Long; use Data::Dumper; use xCAT::PPCcli qw(SUCCESS EXPECT_ERROR RC_ERROR NR_ERROR); +use xCAT::Utils; +use xCAT::TableUtils; +use xCAT::ServiceNodeUtils; use xCAT::NetworkUtils; use xCAT::MsgUtils qw(verbose_message); use xCAT::LparNetbootExp; @@ -90,9 +93,9 @@ sub parse_args { if ( exists($opt{S}) ) { push @network, $_; } else { - $server = xCAT::Utils->getSNformattedhash( $node, "xcat", "node", "primary" ); + $server = xCAT::ServiceNodeUtils->getSNformattedhash( $node, "xcat", "node", "primary" ); foreach my $key ( keys %$server ) { - my $valid_ip = xCAT::Utils->validate_ip( $key ); + my $valid_ip = xCAT::NetworkUtils->validate_ip( $key ); if ( $valid_ip ) { ################################################### # Service node is returned as hostname, Convert @@ -197,7 +200,7 @@ sub parse_args { if ( scalar(@network) != 3 ) { return( usage() ); } - my $result = xCAT::Utils->validate_ip( $opt{C}, $opt{G}, $opt{S} ); + my $result = xCAT::NetworkUtils->validate_ip( $opt{C}, $opt{G}, $opt{S} ); if ( @$result[0] ) { return(usage( @$result[1] )); } @@ -683,7 +686,7 @@ sub getmacs { #my $vcon = $sitetab->getAttribs({key => "conserverondemand"}, 'value'); #there may be something wrong with the conserverondemand attribute. # Currently, the code is not used. So not fix this time. Just keep it here. - my @vcons = xCAT::Utils->get_site_attribute("conserverondemand"); + my @vcons = xCAT::TableUtils->get_site_attribute("conserverondemand"); my $vcon = $vcons[0]; #if ($vcon and $vcon->{"value"} and $vcon->{"value"} eq "yes" ) { if ( defined($vcon) and $vcon eq "yes" ) { diff --git a/perl-xCAT/xCAT/PPCrflash.pm b/perl-xCAT/xCAT/PPCrflash.pm index 232e5821d..9f7520165 100644 --- a/perl-xCAT/xCAT/PPCrflash.pm +++ b/perl-xCAT/xCAT/PPCrflash.pm @@ -8,6 +8,8 @@ use xCAT::Usage; use xCAT::PPCinv; use xCAT::DSHCLI; use xCAT::Table; +use xCAT::Utils; +use xCAT::TableUtils; use Getopt::Long; use File::Spec; use POSIX qw(tmpnam); @@ -320,7 +322,7 @@ sub preprocess_for_rflash { my $request = shift; my $opt = shift; my $callback = $request->{callback}; - my $install_dir = xCAT::Utils->getInstallDir(); + my $install_dir = xCAT::TableUtils->getInstallDir(); my $packages_fw = "$install_dir/packages_fw"; my $c = 0; my $packages_d; diff --git a/perl-xCAT/xCAT/RSYNC.pm b/perl-xCAT/xCAT/RSYNC.pm index 8d1bb2bde..e6e4cd3e9 100644 --- a/perl-xCAT/xCAT/RSYNC.pm +++ b/perl-xCAT/xCAT/RSYNC.pm @@ -5,7 +5,7 @@ package xCAT::RSYNC; # cannot use strict use base xCAT::DSHRemoteShell; - +use xCAT::TableUtils qw(get_site_attribute); # Determine if OS is AIX or Linux # Configure standard locations of commands based on OS @@ -77,7 +77,7 @@ sub remote_copy_command my $usersh=0; if ($^O eq 'aix') { - my @useSSH = xCAT::Utils->get_site_attribute("useSSHonAIX"); + my @useSSH = xCAT::TableUtils->get_site_attribute("useSSHonAIX"); if (defined($useSSH[0])) { $useSSH[0] =~ tr/a-z/A-Z/; # convert to upper if (($useSSH[0] eq "0") || ($useSSH[0] eq "NO")) diff --git a/perl-xCAT/xCAT/Scope.pm b/perl-xCAT/xCAT/Scope.pm index f460e3d7d..f768435d6 100644 --- a/perl-xCAT/xCAT/Scope.pm +++ b/perl-xCAT/xCAT/Scope.pm @@ -1,6 +1,7 @@ package xCAT::Scope; use xCAT::Utils; use xCAT::Table; +use xCAT::ServiceNodeUtils qw(getSNList); sub get_broadcast_scope { my $req = shift; if ($req =~ /xCAT::Scope/) { @@ -10,8 +11,8 @@ sub get_broadcast_scope { if ($req->{_xcatpreprocessed}->[0] == 1) { return [$req]; } #Exit if the packet has been preprocessed in its history my @requests = ({%$req}); #Start with a straight copy to reflect local instance - foreach (xCAT::Utils->getSNList()) { - if (xCAT::Utils->thishostisnot($_)) { + foreach (xCAT::ServiceNodeUtils->getSNList()) { + if (xCAT::NetworkUtils->thishostisnot($_)) { my $reqcopy = {%$req}; $reqcopy->{'_xcatdest'} = $_; $reqcopy->{_xcatpreprocessed}->[0] = 1; @@ -24,7 +25,7 @@ sub get_broadcast_scope { #$sitetab->close; #if ($ent and $ent->{value}) { # foreach (split /,/,$ent->{value}) { - # if (xCAT::Utils->thishostisnot($_)) { + # if (xCAT::NetworkUtils->thishostisnot($_)) { # my $reqcopy = {%$req}; # $reqcopy->{'_xcatdest'} = $_; # push @requests,$reqcopy; diff --git a/perl-xCAT/xCAT/ServiceNodeUtils.pm b/perl-xCAT/xCAT/ServiceNodeUtils.pm new file mode 100644 index 000000000..3aa581e27 --- /dev/null +++ b/perl-xCAT/xCAT/ServiceNodeUtils.pm @@ -0,0 +1,685 @@ +#!/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 +=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->get_AllSN + 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; +} +1; diff --git a/perl-xCAT/xCAT/TableUtils.pm b/perl-xCAT/xCAT/TableUtils.pm new file mode 100644 index 000000000..ab4a5e136 --- /dev/null +++ b/perl-xCAT/xCAT/TableUtils.pm @@ -0,0 +1,1471 @@ +#!/usr/bin/env perl +# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html +package xCAT::TableUtils; + +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 + list_all_nodes + + Arguments: + + Returns: + an array of all define nodes from the nodelist table + Globals: + none + Error: + undef + Example: + @nodes=xCAT::TableUtils->list_all_nodes; + Comments: + none + +=cut + +#------------------------------------------------------------------------ +sub list_all_nodes +{ + require xCAT::Table; + my @nodes; + my @nodelist; + my $nodelisttab; + if ($nodelisttab = xCAT::Table->new("nodelist")) + { + my @attribs = ("node"); + @nodes = $nodelisttab->getAllAttribs(@attribs); + foreach my $node (@nodes) + { + push @nodelist, $node->{node}; + } + } + else + { + xCAT::MsgUtils->message("E", " Could not read the nodelist table\n"); + } + return @nodelist; +} + +#----------------------------------------------------------------------- + +=head3 + list_all_nodegroups + + Arguments: + + Returns: + an array of all define node groups from the nodelist and nodegroup + table + Globals: + none + Error: + undef + Example: + @nodegrps=xCAT::TableUtils->list_all_nodegroups; + Comments: + none + +=cut + +#------------------------------------------------------------------------ +sub list_all_node_groups +{ + require xCAT::Table; + my @grouplist; + my @grouplist2; + my @distinctgroups; + my $nodelisttab; + if ($nodelisttab = xCAT::Table->new("nodelist")) + { + my @attribs = ("groups"); + @grouplist = $nodelisttab->getAllAttribs(@attribs); + + # build a distinct list of unique group names + foreach my $group (@grouplist) + { + my $gnames = $group->{groups}; + my @groupnames = split ",", $gnames; + foreach my $groupname (@groupnames) + { + if (!grep(/$groupname/, @distinctgroups)) + { # not already in list + push @distinctgroups, $groupname; + } + } + } + } + else + { + xCAT::MsgUtils->message("E", " Could not read the nodelist table\n"); + } + $nodelisttab->close; + # now read the nodegroup table + if ($nodelisttab = xCAT::Table->new("nodegroup")) + { + my @attribs = ("groupname"); + @grouplist = $nodelisttab->getAllAttribs(@attribs); + + # build a distinct list of unique group names + foreach my $group (@grouplist) + { + my $groupname = $group->{groupname}; + if (!grep(/$groupname/, @distinctgroups)) + { # not already in list + push @distinctgroups, $groupname; + } + } + $nodelisttab->close; + } + else + { + xCAT::MsgUtils->message("E", " Could not read the nodegroup table\n"); + } + + return @distinctgroups; +} + +#-------------------------------------------------------------------------------- + +=head3 setupSSH + + Generates if needed and Transfers the ssh keys + fOr a userid to setup ssh to the input nodes. + + Arguments: + Array of nodes + 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); + 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 setupSSH +{ + my ($class, $ref_nodes) = @_; + my @nodes = $ref_nodes; + my @badnodes = (); + my $n_str = $nodes[0]; + my $SSHdir = xCAT::TableUtils->getInstallDir() . "/postscripts/_ssh"; + if (!($ENV{'DSH_REMOTE_PASSWORD'})) + { + my $rsp = (); + $rsp->{data}->[0] = + "User password for the ssh key exchange has not been input. xdsh -K cannot complete.\n"; + xCAT::MsgUtils->message("E", $rsp, $::CALLBACK, 1); + return; + + } + + # setup who the keys are coming from and who they are going to + my $from_userid; + my $to_userid; + if (!($ENV{'DSH_FROM_USERID'})) + { + my $rsp = (); + $rsp->{data}->[0] = + "DSH From Userid has not been input. xdsh -K cannot complete.\n"; + xCAT::MsgUtils->message("E", $rsp, $::CALLBACK, 1); + return; + + } + else + { + $from_userid = $ENV{'DSH_FROM_USERID'}; + } + if (!($ENV{'DSH_TO_USERID'})) + { + my $rsp = (); + $rsp->{data}->[0] = + "DSH to Userid has not been input. xdsh -K cannot complete.\n"; + xCAT::MsgUtils->message("E", $rsp, $::CALLBACK, 1); + return; + + } + else + { + $to_userid = $ENV{'DSH_TO_USERID'}; + } + + + # + # if we are running as root + # for non-root users, keys were generated in the xdsh client code + # + + $::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 + my $rc= + xCAT::RemoteShellExp->remoteshellexp("k",$::CALLBACK,$::REMOTE_SHELL); + if ($rc != 0) { + $rsp->{data}->[0] = "remoteshellexp failed generating keys."; + xCAT::MsgUtils->message("E", $rsp, $::CALLBACK); + } + } + + # build the shell copy script, needed Perl not always there + # for root and non-root ids + open(FILE, ">$home/.ssh/copy.sh") + or die "cannot open file $home/.ssh/copy.sh\n"; + print FILE "#!/bin/sh +umask 0077 +home=`egrep \"^$to_userid:\" /etc/passwd | cut -f6 -d :` +if [ $home ]; then + dest_dir=\"\$home/.ssh\" +else + home=`su - root -c pwd` + dest_dir=\"\$home/.ssh\" +fi +mkdir -p \$dest_dir +cat /tmp/$to_userid/.ssh/authorized_keys >> \$home/.ssh/authorized_keys 2>&1 +cp /tmp/$to_userid/.ssh/id_rsa \$home/.ssh/id_rsa 2>&1 +chmod 0600 \$home/.ssh/id_* 2>&1 +rm -f /tmp/$to_userid/.ssh/* 2>&1 +rmdir \"/tmp/$to_userid/.ssh\" +rmdir \"/tmp/$to_userid\" \n"; + + close FILE; + chmod 0777,"$home/.ssh/copy.sh"; + my $auth_key=0; + my $auth_key2=0; + if ($from_userid eq "root") + { + my $rc = xCAT::TableUtils->cpSSHFiles($SSHdir); + if ($rc != 0) + { # error + $rsp->{data}->[0] = "Error running cpSSHFiles.\n"; + xCAT::MsgUtils->message("E", $rsp, $::CALLBACK); + return 1; + + } + if (xCAT::Utils->isMN()) { # if on Management Node + # copy the copy install file to the install directory, if from and + # to userid are root + if ($to_userid eq "root") + { + + my $cmd = " cp $home/.ssh/copy.sh $SSHdir/copy.sh"; + xCAT::Utils->runcmd($cmd, 0); + my $rsp = {}; + if ($::RUNCMD_RC != 0) + { + $rsp->{data}->[0] = "$cmd failed.\n"; + xCAT::MsgUtils->message("E", $rsp, $::CALLBACK); + return (1); + + } + } + } # end is MN + } + else { # from_userid is not root + # build the authorized key files for non-root user + xCAT::Utils->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'}))) { + my $enablenodes; + my $disablenodes; + my @nodelist= split(",", $n_str); + foreach my $n (@nodelist) + { + my $enablessh=xCAT::TableUtils->enablessh($n); + if ($enablessh == 1) { + $enablenodes .= $n; + $enablenodes .= ","; + } else { + $disablenodes .= $n; + $disablenodes .= ","; + } + + } + my $cmd; + if ($enablenodes) { # node on list to setup nodetonodessh + chop $enablenodes; # remove last comma + $ENV{'DSH_ENABLE_SSH'} = "YES"; + my $rc=xCAT::RemoteShellExp->remoteshellexp("s",$::CALLBACK,"/usr/bin/ssh",$enablenodes); + if ($rc != 0) + { + $rsp->{data}->[0] = "remoteshellexp failed sending keys to enablenodes."; + xCAT::MsgUtils->message("E", $rsp, $::CALLBACK); + + } + } + if ($disablenodes) { # node on list to setup nodetonodessh + chop $disablenodes; # remove last comma + my $rc=xCAT::RemoteShellExp->remoteshellexp("s",$::CALLBACK,"/usr/bin/ssh",$disablenodes); + if ($rc != 0) + { + $rsp->{data}->[0] = "remoteshellexp failed sending keys to disablenodes."; + xCAT::MsgUtils->message("E", $rsp, $::CALLBACK); + + } + } + } 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); + if ($rc != 0) + { + $rsp->{data}->[0] = "remoteshellexp failed sending keys."; + xCAT::MsgUtils->message("E", $rsp, $::CALLBACK); + + } + } + + # must always check to see if worked, run test + my @testnodes= split(",", $nodes[0]); + foreach my $n (@testnodes) + { + my $rc= + xCAT::RemoteShellExp->remoteshellexp("t",$::CALLBACK,"/usr/bin/ssh",$n); + if ($rc != 0) + { + push @badnodes, $n; + } + } + + if (@badnodes) + { + my $nstring = join ',', @badnodes; + $rsp->{data}->[0] = + "SSH setup failed for the following nodes: $nstring."; + xCAT::MsgUtils->message("E", $rsp, $::CALLBACK); + return @badnodes; + } + else + { + $rsp->{data}->[0] = "$::REMOTE_SHELL setup is complete."; + xCAT::MsgUtils->message("I", $rsp, $::CALLBACK); + return 0; + } +} + +#-------------------------------------------------------------------------------- + +=head3 cpSSHFiles + + Builds authorized_keyfiles for root + + Arguments: + install directory path + Returns: + + Globals: + $::CALLBACK + Error: + + Example: + xCAT::TableUtils->cpSSHFiles($dir); + + Comments: + none + +=cut + +#-------------------------------------------------------------------------------- + + +sub cpSSHFiles +{ + my ($class, $SSHdir) = @_; + my ($cmd, $rc); + my $rsp = {}; + if ($::VERBOSE) + { + $rsp->{data}->[0] = "Copying SSH Keys"; + xCAT::MsgUtils->message("I", $rsp, $::CALLBACK); + } + my $home = xCAT::Utils->getHomeDir("root"); + + + if (xCAT::Utils->isMN()) { # if on Management Node + if (!(-e "$home/.ssh/id_rsa.pub")) # only using rsa + { + $rsp->{data}->[0] = "Public key id_rsa.pub was missing in the .ssh directory."; + xCAT::MsgUtils->message("E", $rsp, $::CALLBACK); + return 1; + } + # copy to id_rsa public key to authorized_keys in the install directory + my $authorized_keys = "$SSHdir/authorized_keys"; + # changed from identity.pub + $cmd = " cp $home/.ssh/id_rsa.pub $authorized_keys"; + xCAT::Utils->runcmd($cmd, 0); + $rsp = {}; + if ($::RUNCMD_RC != 0) + { + $rsp->{data}->[0] = "$cmd failed.\n"; + xCAT::MsgUtils->message("E", $rsp, $::CALLBACK); + return (1); + + } + else + { + if ($::VERBOSE) + { + $rsp->{data}->[0] = "$cmd succeeded.\n"; + xCAT::MsgUtils->message("I", $rsp, $::CALLBACK); + } + } + } # end is MN + + # on MN and SN + # make tmp directory to hold authorized_keys for node transfer + if (!(-e "$home/.ssh/tmp")) { + $cmd = " mkdir $home/.ssh/tmp"; + xCAT::Utils->runcmd($cmd, 0); + $rsp = {}; + if ($::RUNCMD_RC != 0) + { + $rsp->{data}->[0] = "$cmd failed.\n"; + xCAT::MsgUtils->message("E", $rsp, $::CALLBACK); + return (1); + + } + } + # create authorized_keys file + if (xCAT::Utils->isMN()) { # if on Management Node + $cmd = " cp $home/.ssh/id_rsa.pub $home/.ssh/tmp/authorized_keys"; + } else { # SN + $cmd = " cp $home/.ssh/authorized_keys $home/.ssh/tmp/authorized_keys"; + } + xCAT::Utils->runcmd($cmd, 0); + $rsp = {}; + if ($::RUNCMD_RC != 0) + { + $rsp->{data}->[0] = "$cmd failed.\n"; + xCAT::MsgUtils->message("E", $rsp, $::CALLBACK); + return (1); + + } + else + { + chmod 0600, "$home/.ssh/tmp/authorized_keys"; + if ($::VERBOSE) + { + $rsp->{data}->[0] = "$cmd succeeded.\n"; + xCAT::MsgUtils->message("I", $rsp, $::CALLBACK); + } + } + + return (0); +} +#------------------------------------------------------------------------------- + +=head3 GetNodeOSARCH + Reads the database for the OS and Arch of the input Node + Arguments: + Node + Returns: + $et->{'os'} + $et->{'arch'} + Globals: + none + Error: + none + Example: + $master=(xCAT::TableUtils->GetNodeOSARCH($node)) + Comments: + none +=cut + +#------------------------------------------------------------------------------- +sub GetNodeOSARCH +{ + require xCAT::Table; + my ($class, $node) = @_; + my $noderestab = xCAT::Table->new('noderes'); + my $typetab = xCAT::Table->new('nodetype'); + unless ($noderestab and $typetab) + { + xCAT::MsgUtils->message('S', + "Unable to open noderes or nodetype table.\n"); + return 1; + } + my $et = $typetab->getNodeAttribs($node, ['os', 'arch']); + unless ($et and $et->{'os'} and $et->{'arch'}) + { + xCAT::MsgUtils->message('S', + "No os/arch setting in nodetype table for $node.\n"); + return 1; + } + + return $et; + +} + +#------------------------------------------------------------------------------- + +=head3 logEventsToDatabase + Logs the given events info to the xCAT's 'eventlog' database + Arguments: + arrayref -- A pointer to an array. Each element is a hash that contains an events. + The hash should contain the at least one of the following keys: + eventtime -- The format is "yyyy-mm-dd hh:mm:ss". + If omitted, the current date and time will be used. + monitor -- The name of the monitor that monitors this event. + monnode -- The node that monitors this event. + node -- The node where the event occurred. + application -- The application that reports the event. + component -- The component where the event occurred. + id -- The location or the resource name where the event occurred. + severity -- The severity of the event. Valid values are: informational, warning, critical. + message -- The full description of the event. + rawdata -- The data that associated with the event. + Returns: + (ret code, error message) + Example: + my @a=(); + my $event={ + eventtime=>"2009-07-28 23:02:03", + node => 'node1', + rawdata => 'kjdlkfajlfjdlksaj', + }; + push (@a, $event); + + my $event1={ + node => 'cu03cp', + monnode => 'cu03sv', + application => 'RMC', + component => 'IBM.Sensor', + id => 'AIXErrorLogSensor', + severity => 'warning', + }; + push(@a, $event1); + xCAT::TableUtils->logEventsToDatabase(\@a); + +=cut + +#------------------------------------------------------------------------------- +sub logEventsToDatabase +{ + require xCAT::Table; + my $pEvents = shift; + if (($pEvents) && ($pEvents =~ /xCAT::Utils/)) + { + $pEvents = shift; + } + + if (($pEvents) && (@$pEvents > 0)) + { + my $currtime; + my $tab = xCAT::Table->new("eventlog", -create => 1, -autocommit => 0); + if (!$tab) + { + return (1, "The evnetlog table cannot be opened."); + } + + foreach my $event (@$pEvents) + { + + #create event time if it does not exist + if (!exists($event->{eventtime})) + { + if (!$currtime) + { + my ( + $sec, $min, $hour, $mday, $mon, + $year, $wday, $yday, $isdst + ) + = localtime(time); + $currtime = sprintf("%04d-%02d-%02d %02d:%02d:%02d", + $year + 1900, $mon + 1, $mday, + $hour, $min, $sec); + } + $event->{eventtime} = $currtime; + } + my @ret = $tab->setAttribs(undef, $event); + if (@ret > 1) { return (1, $ret[1]); } + } + $tab->commit; + } + + return (0, ""); +} + + +#------------------------------------------------------------------------------- + +=head3 logEventsToTealDatabase + Logs the given events info to the TEAL's 'x_tealeventlog' database + Arguments: + arrayref -- A pointer to an array. Each element is a hash that contains an events. + Returns: + (ret code, error message) + +=cut + +#------------------------------------------------------------------------------- +sub logEventsToTealDatabase +{ + require xCAT::Table; + my $pEvents = shift; + if (($pEvents) && ($pEvents =~ /xCAT::Utils/)) + { + $pEvents = shift; + } + + if (($pEvents) && (@$pEvents > 0)) + { + my $currtime; + my $tab = xCAT::Table->new("x_tealeventlog", -create => 1, -autocommit => 0); + if (!$tab) + { + return (1, "The x_tealeventlog table cannot be opened."); + } + + foreach my $event (@$pEvents) + { + my @ret = $tab->setAttribs(undef, $event); + if (@ret > 1) { return (1, $ret[1]); } + } + $tab->commit; + } + + return (0, ""); +} + +#------------------------------------------------------------------------------- + +=head3 setAppStatus + Description: + Set an AppStatus value for a specific application in the nodelist + appstatus attribute for a list of nodes + Arguments: + @nodes + $application + $status + Returns: + Return result of call to setNodesAttribs + Globals: + none + Error: + none + Example: + xCAT::TableUtils->setAppStatus(\@nodes,$application,$status); + Comments: + +=cut + +#----------------------------------------------------------------------------- + +sub setAppStatus +{ + require xCAT::Table; + + my ($class, $nodes_ref, $application, $status) = @_; + my @nodes = @$nodes_ref; + + #get current local time to set in appstatustime attribute + my ( + $sec, $min, $hour, $mday, $mon, + $year, $wday, $yday, $isdst + ) + = localtime(time); + my $currtime = sprintf("%02d-%02d-%04d %02d:%02d:%02d", + $mon + 1, $mday, $year + 1900, + $hour, $min, $sec); + + my $nltab = xCAT::Table->new('nodelist'); + my $nodeappstat = $nltab->getNodesAttribs(\@nodes,['appstatus']); + + my %new_nodeappstat; + foreach my $node (keys %$nodeappstat) { + if ( $node =~ /^\s*$/ ) { next; } # Skip blank node names + my $new_appstat = ""; + my $changed = 0; + + # Search current appstatus and change if app entry exists + my $cur_appstat = $nodeappstat->{$node}->[0]->{appstatus}; + if ($cur_appstat) { + my @appstatus_entries = split(/,/,$cur_appstat); + foreach my $appstat (@appstatus_entries) { + my ($app, $stat) = split(/=/,$appstat); + if ($app eq $application) { + $new_appstat .= ",$app=$status"; + $changed = 1; + } else { + $new_appstat .= ",$appstat"; + } + } + } + # If no app entry exists, add it + if (!$changed){ + $new_appstat .= ",$application=$status"; + } + $new_appstat =~ s/^,//; + $new_nodeappstat{$node}->{appstatus} = $new_appstat; + $new_nodeappstat{$node}->{appstatustime} = $currtime; + } + + return $nltab->setNodesAttribs(\%new_nodeappstat); + +} + + +#------------------------------------------------------------------------------- + +=head3 getAppStatus + Description: + Get an AppStatus value for a specific application from the + nodelist appstatus attribute for a list of nodes + Arguments: + @nodes + $application + Returns: + a hashref of nodes set to application status value + Globals: + none + Error: + none + Example: + my $appstatus = $xCAT::TableUtils->getAppStatus(\@nodes,$application); + my $node1_status = $appstatus->{node1}; + Comments: + +=cut + +#----------------------------------------------------------------------------- + +sub getAppStatus +{ + require xCAT::Table; + + my ($class, $nodes_ref, $application) = @_; + my @nodes = @$nodes_ref; + + my $nltab = xCAT::Table->new('nodelist'); + my $nodeappstat = $nltab->getNodesAttribs(\@nodes,['appstatus']); + + my $ret_nodeappstat; + foreach my $node (keys %$nodeappstat) { + my $cur_appstat = $nodeappstat->{$node}->[0]->{appstatus}; + my $found = 0; + if ($cur_appstat) { + my @appstatus_entries = split(/,/,$cur_appstat); + foreach my $appstat (@appstatus_entries) { + my ($app, $stat) = split(/=/,$appstat); + if ($app eq $application) { + $ret_nodeappstat->{$node} = $stat; + $found = 1; + } + } + } + # If no app entry exists, return empty + if (!$found){ + $ret_nodeappstat->{$node} = ""; + } + } + + return $ret_nodeappstat; + +} + +#----------------------------------------------------------------------- + +=head3 + get_site_attribute + + Arguments: + + Returns: + The value of the attribute requested from the site table + Globals: + none + Error: + undef + Example: + @attr=xCAT::TableUtils->get_site_attribute($attribute); + Comments: + none + +=cut + +#------------------------------------------------------------------------ +sub get_site_attribute +{ + require xCAT::Table; + my ($class, $attr) = @_; + + my $values; + if (defined($::XCATSITEVALS{$attr})) { + $values = ($::XCATSITEVALS{$attr}); + } else { + my $sitetab = xCAT::Table->new('site'); + if ($sitetab) + { + (my $ref) = $sitetab->getAttribs({key => $attr}, 'value'); + if ($ref) + { + $values = $ref->{value}; + } + } + else + { + xCAT::MsgUtils->message("E", " Could not read the site table\n"); + + } + $sitetab->close; + } + return $values; +} + + +#-------------------------------------------------------------------------------- + +=head3 getInstallDir + + Get location of the directory, used to hold the node deployment packages. + + Arguments: + none + Returns: + path to install directory defined at site.installdir. + Globals: + none + Error: + none + Example: + $installdir = xCAT::TableUtils->getInstallDir(); + Comments: + none + +=cut + +#-------------------------------------------------------------------------------- + +sub getInstallDir +{ + # Default installdir location. Used by default in most Linux distros. + my $installdir = "/install"; + + # Try to lookup real installdir place. + my @installdir1 = xCAT::TableUtils->get_site_attribute("installdir"); + + # Use fetched value, incase successful database lookup. + if ($installdir1[0]) + { + $installdir = $installdir1[0]; + } + + return $installdir; +} + + +#-------------------------------------------------------------------------------- + +=head3 getTftpDir + + Get location of the directory, used to hold network boot files. + + Arguments: + none + Returns: + path to TFTP directory defined at site.tftpdir. + Globals: + none + Error: + none + Example: + $tftpdir = xCAT::TableUtils->getTftpDir(); + Comments: + none + +=cut + +#-------------------------------------------------------------------------------- + +sub getTftpDir +{ + # Default tftpdir location. Used by default in most Linux distros. + my $tftpdir = "/tftpboot"; + + # Try to lookup real tftpdir place. + my @tftpdir1 = xCAT::TableUtils->get_site_attribute("tftpdir"); + + # Use fetched value, incase successful database lookup. + if ($tftpdir1[0]) + { + $tftpdir = $tftpdir1[0]; + } + + return $tftpdir; +} + +#------------------------------------------------------------------------------- + +=head3 GetMasterNodeName + Reads the database for the Master node name for the input node + Arguments: + Node + Returns: + MasterHostName + Globals: + none + Error: + none + Example: + $master=(xCAT::TableUtils->GetMasterNodeName($node)) + Comments: + none +=cut + +#------------------------------------------------------------------------------- +sub GetMasterNodeName +{ + require xCAT::Table; + my ($class, $node) = @_; + my $master; + my $noderestab = xCAT::Table->new('noderes'); + my $typetab = xCAT::Table->new('nodetype'); + unless ($noderestab and $typetab) + { + xCAT::MsgUtils->message('S', + "Unable to open noderes or nodetype table.\n"); + return 1; + } + #my $sitetab = xCAT::Table->new('site'); + #(my $et) = $sitetab->getAttribs({key => "master"}, 'value'); + #if ($et and $et->{value}) + #{ + # $master = $et->{value}; + #} + my @masters = xCAT::TableUtils->get_site_attribute("master"); + $master = $masters[0]; + + my $et = $noderestab->getNodeAttribs($node, ['xcatmaster']); + if ($et and $et->{'xcatmaster'}) + { + $master = $et->{'xcatmaster'}; + } + unless ($master) + { + xCAT::MsgUtils->message('S', "Unable to identify master for $node.\n"); + #$sitetab->close; + $noderestab->close; + $typetab->close; + return 1; + } + + #$sitetab->close; + $noderestab->close; + $typetab->close; + return $master; +} + + +#----------------------------------------------------------------------------- + +=head3 create_postscripts_tar + + This routine will tar and compress the /install/postscripts directory + and place in /install/autoinst/xcat_postscripts.Z + + input: none + output: + example: $rc=xCAT::TableUtils->create_postscripts_tar(); + +=cut + +#----------------------------------------------------------------------------- +sub create_postscripts_tar +{ + my ($class) = @_; + my $installdir = xCAT::TableUtils->getInstallDir(); + my $cmd; + if (!(-e "$installdir/autoinst")) + { + mkdir("$installdir/autoinst"); + } + + $cmd = + "cd $installdir/postscripts; tar -cf $installdir/autoinst/xcatpost.tar * .ssh/* _xcat/*; gzip -f $installdir/autoinst/xcatpost.tar"; + my @result = xCAT::Utils->runcmd($cmd, 0); + if ($::RUNCMD_RC != 0) + { + xCAT::MsgUtils->message("S", "Error from $cmd\n"); + return $::RUNCMD_RC; + } + + # for AIX add an entry to the /etc/tftpaccess.ctrl file so + # we can tftp the tar file from the node + if (xCAT::Utils->isAIX()) + { + my $tftpctlfile = "/etc/tftpaccess.ctl"; + my $entry = "allow:$installdir/autoinst/xcatpost.tar.gz"; + + # see if there is already an entry + my $cmd = "cat $tftpctlfile | grep xcatpost"; + my @result = xCAT::Utils->runcmd("$cmd", -1); + if ($::RUNCMD_RC != 0) + { + + # not found so add it + unless (open(TFTPFILE, ">>$tftpctlfile")) + { + xCAT::MsgUtils->message("S", "Could not open $tftpctlfile.\n"); + return $::RUNCMD_RC; + } + + print TFTPFILE $entry; + + close(TFTPFILE); + } + } + return 0; +} + +#----------------------------------------------------------------------------- + +=head3 get_site_Master + + Reads the site table for the Master attribute and returns it. + input: none + output : value of site.Master attribute , blank is an error + example: $Master =xCAT::TableUtils->get_site_Master(); + +=cut + +#----------------------------------------------------------------------------- + +sub get_site_Master +{ + if ($::XCATSITEVALS{master}) { + return $::XCATSITEVALS{master}; + } + require xCAT::Table; + my $Master; + my $sitetab = xCAT::Table->new('site'); + (my $et) = $sitetab->getAttribs({key => "master"}, 'value'); + if ($et and $et->{value}) + { + $Master = $et->{value}; + } + else + { +# this msg can be missleading +# xCAT::MsgUtils->message('E', +# "Unable to read site table for Master attribute.\n"); + } + return $Master; +} + + +#------------------------------------------------------------------------------- + +=head3 checkCredFiles + Checks the various credential files on the Management Node to + make sure the permission are correct for using and transferring + to the nodes and service nodes. + Also removes /install/postscripts/etc/xcat/cfgloc if found + Arguments: + $callback + Returns: + 0 - ok + Globals: + none + Error: + warnings of possible missing files and directories + Example: + my $rc=xCAT::TableUtils->checkCreds + Comments: + none + +=cut + +#------------------------------------------------------------------------------- +sub checkCredFiles +{ + my $lib = shift; + my $cb = shift; + my $installdir = xCAT::TableUtils->getInstallDir(); + my $dir = "$installdir/postscripts/_xcat"; + if (-d $dir) + { + my $file = "$dir/ca.pem"; + if (-e $file) + { + + my $cmd = "/bin/chmod 0644 $file"; + my $outref = xCAT::Utils->runcmd("$cmd", 0); + if ($::RUNCMD_RC != 0) + { + my $rsp = {}; + $rsp->{data}->[0] = "Error on command: $cmd"; + xCAT::MsgUtils->message("I", $rsp, $cb); + + } + } + else + { # ca.pem missing + my $rsp = {}; + $rsp->{data}->[0] = "Error: $file is missing. Run xcatconfig (no force)"; + xCAT::MsgUtils->message("I", $rsp, $cb); + } + } + else + { + my $rsp = {}; + $rsp->{data}->[0] = "Error: $dir is missing."; + xCAT::MsgUtils->message("I", $rsp, $cb); + } + + + $dir = "$installdir/postscripts/ca"; + if (-d $dir) + { + my $file = "$dir/ca-cert.pem"; + if (-e $file) + { + + my $cmd = "/bin/chmod 0644 $file"; + my $outref = xCAT::Utils->runcmd("$cmd", 0); + if ($::RUNCMD_RC != 0) + { + my $rsp = {}; + $rsp->{data}->[0] = "Error on command: $cmd"; + xCAT::MsgUtils->message("I", $rsp, $cb); + + } + } + else + { # ca_cert.pem missing + my $rsp = {}; + $rsp->{data}->[0] = "Error: $file is missing. Run xcatconfig (no force)"; + xCAT::MsgUtils->message("I", $rsp, $cb); + } + } + else + { + my $rsp = {}; + $rsp->{data}->[0] = "Error: $dir is missing."; + xCAT::MsgUtils->message("I", $rsp, $cb); + } + + + # ssh hostkeys + $dir = "$installdir/postscripts/hostkeys"; + if (-d $dir) + { + my $file = "$dir/ssh_host_key.pub"; + if (-e $file) + { + my $file2 = "$dir/*.pub"; # all public keys + my $cmd = "/bin/chmod 0644 $file2"; + my $outref = xCAT::Utils->runcmd("$cmd", 0); + if ($::RUNCMD_RC != 0) + { + my $rsp = {}; + $rsp->{data}->[0] = "Error on command: $cmd"; + xCAT::MsgUtils->message("I", $rsp, $cb); + + } + } + else + { # hostkey missing + my $rsp = {}; + $rsp->{data}->[0] = "Error: $file is missing. Run xcatconfig (no force)"; + xCAT::MsgUtils->message("I", $rsp, $cb); + } + } + else + { + my $rsp = {}; + $rsp->{data}->[0] = "Error: $dir is missing."; + xCAT::MsgUtils->message("I", $rsp, $cb); + } + # ssh hostkeys + $dir = "/etc/xcat/hostkeys"; + if (-d $dir) + { + my $file = "$dir/ssh_host_key.pub"; + if (-e $file) + { + my $file2 = "$dir/*.pub"; # all public keys + my $cmd = "/bin/chmod 0644 $file2"; + my $outref = xCAT::Utils->runcmd("$cmd", 0); + if ($::RUNCMD_RC != 0) + { + my $rsp = {}; + $rsp->{data}->[0] = "Error on command: $cmd"; + xCAT::MsgUtils->message("I", $rsp, $cb); + + } + } + else + { # hostkey missing + my $rsp = {}; + $rsp->{data}->[0] = "Error: $file is missing. Run xcatconfig (no force)"; + xCAT::MsgUtils->message("I", $rsp, $cb); + } + } + else + { + my $rsp = {}; + $rsp->{data}->[0] = "Error: $dir is missing."; + xCAT::MsgUtils->message("I", $rsp, $cb); + } + + # ssh directory + $dir = "$installdir/postscripts/_ssh"; + + if (-d $dir) + { + my $file = "$dir/authorized_keys"; + if (-e $file) + { + my $file2 = "$dir/authorized_keys*"; + my $cmd = "/bin/chmod 0644 $file2"; + my $outref = xCAT::Utils->runcmd("$cmd", 0); + if ($::RUNCMD_RC != 0) + { + my $rsp = {}; + $rsp->{data}->[0] = "Error on command: $cmd"; + xCAT::MsgUtils->message("I", $rsp, $cb); + + } + + # make install script executable + $file2 = "$dir/copy.sh"; + if (-e $file2) + { + my $cmd = "/bin/chmod 0744 $file2"; + my $outref = xCAT::Utils->runcmd("$cmd", 0); + if ($::RUNCMD_RC != 0) + { + my $rsp = {}; + $rsp->{data}->[0] = "Error on command: $cmd"; + xCAT::MsgUtils->message("I", $rsp, $cb); + + } + } + } + else + { # authorized keys missing + my $rsp = {}; + $rsp->{data}->[0] = "Error: $file is missing. Run xcatconfig (no force)"; + xCAT::MsgUtils->message("I", $rsp, $cb); + } + } + else + { + my $rsp = {}; + $rsp->{data}->[0] = "Error: $dir is missing."; + xCAT::MsgUtils->message("I", $rsp, $cb); + } + + # remove any old cfgloc files + my $file = "$installdir/postscripts/etc/xcat/cfgloc"; + if (-e $file) + { + + my $cmd = "/bin/rm $file"; + my $outref = xCAT::Utils->runcmd("$cmd", 0); + if ($::RUNCMD_RC != 0) + { + my $rsp = {}; + $rsp->{data}->[0] = "Error on command: $cmd"; + xCAT::MsgUtils->message("I", $rsp, $cb); + + } + } + +} + +#------------------------------------------------------------------------------- + +=head3 enableSSH + Description: + Reads the site.sshbetweennodes attribute and determines + if the input node should be enabled to ssh between nodes + Arguments: + $node + Returns: + 1 = enable ssh + 0 = do not enable ssh + Globals: + none + Error: + none + Example: + my $eable = $xCAT::TableUtils::enablessh($node); + Comments: + +=cut + +#----------------------------------------------------------------------------- + +sub enablessh +{ + + require xCAT::Table; + my ($class, $node) = @_; + my $enablessh=1; + if (xCAT::Utils->isSN($node)) + { + $enablessh=1; # service nodes always enabled + } + else + { + + # if not a service node we need to check, before enabling + my $values; + #if (keys %::XCATSITEVALS) { + # $values=$::XCATSITEVALS{sshbetweennodes}; + #} else { + # my $sitetab = xCAT::Table->new('site'); + # my $attr = "sshbetweennodes"; + # my $ref = $sitetab->getAttribs({key => $attr}, 'value'); + # if ($ref) { + # $values = $ref->{value}; + # } + #} + my @vals = xCAT::TableUtils->get_site_attribute("sshbetweennodes"); + $values = $vals[0]; + if ($values) { + my @groups = split(/,/, $values); + if (grep(/^ALLGROUPS$/, @groups)) + { + $enablessh=1; + } + else + { + if (grep(/^NOGROUPS$/, @groups)) + { + $enablessh=0; + } + else + { # check to see if the node is a member of a group + my $ismember = 0; + foreach my $group (@groups) + { + $ismember = xCAT::Utils->isMemberofGroup($node, $group); + if ($ismember == 1) + { + last; + } + } + if ($ismember == 1) + { + $enablessh=1; + } + else + { + $enablessh=0; + } + } + } + } + else + { # does not exist, set default + $enablessh=1; + + } + } + + return $enablessh; + +} + + +#----------------------------------------------------------------------------- + + +=head3 getrootimage + Get the directory of root image for a node; + Note: This subroutine only works for diskless node + + Arguments: + $node + Returns: + string - directory of the root image + undef - this is not a diskless node or the root image does not existed + Globals: + none + Error: + Example: + my $node_syncfile=xCAT::TableUtils->getrootimage($node); + +=cut + +#----------------------------------------------------------------------------- + +sub getrootimage() +{ + require xCAT::Table; + my $node = shift; + my $installdir = xCAT::TableUtils->getInstallDir(); + if (($node) && ($node =~ /xCAT::Utils/)) + { + $node = shift; + } + # get the os,arch,profile attributes for the nodes + my $nodetype_t = xCAT::Table->new('nodetype'); + unless ($nodetype_t) { + return ; + } + my $nodetype_v = $nodetype_t->getNodeAttribs($node, ['profile','os','arch']); + my $profile = $nodetype_v->{'profile'}; + my $os = $nodetype_v->{'os'}; + my $arch = $nodetype_v->{'arch'}; + + if ($^O eq "linux") { + my $rootdir = "$installdir/netboot/$os/$arch/$profile/rootimg/"; + if (-d $rootdir) { + return $rootdir; + } else { + return undef; + } + } else { + # For AIX + } +} +1; diff --git a/perl-xCAT/xCAT/Utils.pm b/perl-xCAT/xCAT/Utils.pm index 0fa8d9ca6..854271c11 100644 --- a/perl-xCAT/xCAT/Utils.pm +++ b/perl-xCAT/xCAT/Utils.pm @@ -43,7 +43,7 @@ require DBI; our @ISA = qw(Exporter); our @EXPORT_OK = qw(genpassword runcmd3); -my $utildata; #data to persist locally + #-------------------------------------------------------------------------------- =head1 xCAT::Utils @@ -583,126 +583,6 @@ sub close_delete_file unlink($file_name); } -#----------------------------------------------------------------------- - -=head3 - list_all_nodes - - Arguments: - - Returns: - an array of all define nodes from the nodelist table - Globals: - none - Error: - undef - Example: - @nodes=xCAT::Utils->list_all_nodes; - Comments: - none - -=cut - -#------------------------------------------------------------------------ -sub list_all_nodes -{ - require xCAT::Table; - my @nodes; - my @nodelist; - my $nodelisttab; - if ($nodelisttab = xCAT::Table->new("nodelist")) - { - my @attribs = ("node"); - @nodes = $nodelisttab->getAllAttribs(@attribs); - foreach my $node (@nodes) - { - push @nodelist, $node->{node}; - } - } - else - { - xCAT::MsgUtils->message("E", " Could not read the nodelist table\n"); - } - return @nodelist; -} - -#----------------------------------------------------------------------- - -=head3 - list_all_nodegroups - - Arguments: - - Returns: - an array of all define node groups from the nodelist and nodegroup - table - Globals: - none - Error: - undef - Example: - @nodegrps=xCAT::Utils->list_all_nodegroups; - Comments: - none - -=cut - -#------------------------------------------------------------------------ -sub list_all_node_groups -{ - require xCAT::Table; - my @grouplist; - my @grouplist2; - my @distinctgroups; - my $nodelisttab; - if ($nodelisttab = xCAT::Table->new("nodelist")) - { - my @attribs = ("groups"); - @grouplist = $nodelisttab->getAllAttribs(@attribs); - - # build a distinct list of unique group names - foreach my $group (@grouplist) - { - my $gnames = $group->{groups}; - my @groupnames = split ",", $gnames; - foreach my $groupname (@groupnames) - { - if (!grep(/$groupname/, @distinctgroups)) - { # not already in list - push @distinctgroups, $groupname; - } - } - } - } - else - { - xCAT::MsgUtils->message("E", " Could not read the nodelist table\n"); - } - $nodelisttab->close; - # now read the nodegroup table - if ($nodelisttab = xCAT::Table->new("nodegroup")) - { - my @attribs = ("groupname"); - @grouplist = $nodelisttab->getAllAttribs(@attribs); - - # build a distinct list of unique group names - foreach my $group (@grouplist) - { - my $groupname = $group->{groupname}; - if (!grep(/$groupname/, @distinctgroups)) - { # not already in list - push @distinctgroups, $groupname; - } - } - $nodelisttab->close; - } - else - { - xCAT::MsgUtils->message("E", " Could not read the nodegroup table\n"); - } - - return @distinctgroups; -} #----------------------------------------------------------------------- @@ -773,55 +653,6 @@ sub isMemberofGroup #----------------------------------------------------------------------- -=head3 - get_site_attribute - - Arguments: - - Returns: - The value of the attribute requested from the site table - Globals: - none - Error: - undef - Example: - @attr=xCAT::Utils->get_site_attribute($attribute); - Comments: - none - -=cut - -#------------------------------------------------------------------------ -sub get_site_attribute -{ - require xCAT::Table; - my ($class, $attr) = @_; - - my $values; - if (defined($::XCATSITEVALS{$attr})) { - $values = ($::XCATSITEVALS{$attr}); - } else { - my $sitetab = xCAT::Table->new('site'); - if ($sitetab) - { - (my $ref) = $sitetab->getAttribs({key => $attr}, 'value'); - if ($ref) - { - $values = $ref->{value}; - } - } - else - { - xCAT::MsgUtils->message("E", " Could not read the site table\n"); - - } - $sitetab->close; - } - return $values; -} - -#----------------------------------------------------------------------- - =head3 add_cron_job This function adds a new cron job. @@ -1419,86 +1250,6 @@ sub runxcmd_output #-------------------------------------------------------------------------------- -=head3 getInstallDir - - Get location of the directory, used to hold the node deployment packages. - - Arguments: - none - Returns: - path to install directory defined at site.installdir. - Globals: - none - Error: - none - Example: - $installdir = xCAT::Utils->getInstallDir(); - Comments: - none - -=cut - -#-------------------------------------------------------------------------------- - -sub getInstallDir -{ - # Default installdir location. Used by default in most Linux distros. - my $installdir = "/install"; - - # Try to lookup real installdir place. - my @installdir1 = xCAT::Utils->get_site_attribute("installdir"); - - # Use fetched value, incase successful database lookup. - if ($installdir1[0]) - { - $installdir = $installdir1[0]; - } - - return $installdir; -} - -#-------------------------------------------------------------------------------- - -=head3 getTftpDir - - Get location of the directory, used to hold network boot files. - - Arguments: - none - Returns: - path to TFTP directory defined at site.tftpdir. - Globals: - none - Error: - none - Example: - $tftpdir = xCAT::Utils->getTftpDir(); - Comments: - none - -=cut - -#-------------------------------------------------------------------------------- - -sub getTftpDir -{ - # Default tftpdir location. Used by default in most Linux distros. - my $tftpdir = "/tftpboot"; - - # Try to lookup real tftpdir place. - my @tftpdir1 = xCAT::Utils->get_site_attribute("tftpdir"); - - # Use fetched value, incase successful database lookup. - if ($tftpdir1[0]) - { - $tftpdir = $tftpdir1[0]; - } - - return $tftpdir; -} - -#-------------------------------------------------------------------------------- - =head3 getHomeDir Get the path the user home directory from /etc/passwd. @@ -1546,477 +1297,7 @@ sub getHomeDir return $homedir; } -#-------------------------------------------------------------------------------- -=head3 setupSSH - - Generates if needed and Transfers the ssh keys - fOr a userid to setup ssh to the input nodes. - - Arguments: - Array of nodes - 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::Utils->setupSSH(@target_nodes); - 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 setupSSH -{ - my ($class, $ref_nodes) = @_; - my @nodes = $ref_nodes; - my @badnodes = (); - my $n_str = $nodes[0]; - my $SSHdir = getInstallDir() . "/postscripts/_ssh"; - if (!($ENV{'DSH_REMOTE_PASSWORD'})) - { - my $rsp = (); - $rsp->{data}->[0] = - "User password for the ssh key exchange has not been input. xdsh -K cannot complete.\n"; - xCAT::MsgUtils->message("E", $rsp, $::CALLBACK, 1); - return; - - } - - # setup who the keys are coming from and who they are going to - my $from_userid; - my $to_userid; - if (!($ENV{'DSH_FROM_USERID'})) - { - my $rsp = (); - $rsp->{data}->[0] = - "DSH From Userid has not been input. xdsh -K cannot complete.\n"; - xCAT::MsgUtils->message("E", $rsp, $::CALLBACK, 1); - return; - - } - else - { - $from_userid = $ENV{'DSH_FROM_USERID'}; - } - if (!($ENV{'DSH_TO_USERID'})) - { - my $rsp = (); - $rsp->{data}->[0] = - "DSH to Userid has not been input. xdsh -K cannot complete.\n"; - xCAT::MsgUtils->message("E", $rsp, $::CALLBACK, 1); - return; - - } - else - { - $to_userid = $ENV{'DSH_TO_USERID'}; - } - - - # - # if we are running as root - # for non-root users, keys were generated in the xdsh client code - # - - $::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 - my $rc= - xCAT::RemoteShellExp->remoteshellexp("k",$::CALLBACK,$::REMOTE_SHELL); - if ($rc != 0) { - $rsp->{data}->[0] = "remoteshellexp failed generating keys."; - xCAT::MsgUtils->message("E", $rsp, $::CALLBACK); - } - } - - # build the shell copy script, needed Perl not always there - # for root and non-root ids - open(FILE, ">$home/.ssh/copy.sh") - or die "cannot open file $home/.ssh/copy.sh\n"; - print FILE "#!/bin/sh -umask 0077 -home=`egrep \"^$to_userid:\" /etc/passwd | cut -f6 -d :` -if [ $home ]; then - dest_dir=\"\$home/.ssh\" -else - home=`su - root -c pwd` - dest_dir=\"\$home/.ssh\" -fi -mkdir -p \$dest_dir -cat /tmp/$to_userid/.ssh/authorized_keys >> \$home/.ssh/authorized_keys 2>&1 -cp /tmp/$to_userid/.ssh/id_rsa \$home/.ssh/id_rsa 2>&1 -chmod 0600 \$home/.ssh/id_* 2>&1 -rm -f /tmp/$to_userid/.ssh/* 2>&1 -rmdir \"/tmp/$to_userid/.ssh\" -rmdir \"/tmp/$to_userid\" \n"; - - close FILE; - chmod 0777,"$home/.ssh/copy.sh"; - my $auth_key=0; - my $auth_key2=0; - if ($from_userid eq "root") - { - my $rc = xCAT::Utils->cpSSHFiles($SSHdir); - if ($rc != 0) - { # error - $rsp->{data}->[0] = "Error running cpSSHFiles.\n"; - xCAT::MsgUtils->message("E", $rsp, $::CALLBACK); - return 1; - - } - if (xCAT::Utils->isMN()) { # if on Management Node - # copy the copy install file to the install directory, if from and - # to userid are root - if ($to_userid eq "root") - { - - my $cmd = " cp $home/.ssh/copy.sh $SSHdir/copy.sh"; - xCAT::Utils->runcmd($cmd, 0); - my $rsp = {}; - if ($::RUNCMD_RC != 0) - { - $rsp->{data}->[0] = "$cmd failed.\n"; - xCAT::MsgUtils->message("E", $rsp, $::CALLBACK); - return (1); - - } - } - } # end is MN - } - else { # from_userid is not root - # build the authorized key files for non-root user - xCAT::Utils->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'}))) { - my $enablenodes; - my $disablenodes; - my @nodelist= split(",", $n_str); - foreach my $n (@nodelist) - { - my $enablessh=xCAT::Utils->enablessh($n); - if ($enablessh == 1) { - $enablenodes .= $n; - $enablenodes .= ","; - } else { - $disablenodes .= $n; - $disablenodes .= ","; - } - - } - my $cmd; - if ($enablenodes) { # node on list to setup nodetonodessh - chop $enablenodes; # remove last comma - $ENV{'DSH_ENABLE_SSH'} = "YES"; - my $rc=xCAT::RemoteShellExp->remoteshellexp("s",$::CALLBACK,"/usr/bin/ssh",$enablenodes); - if ($rc != 0) - { - $rsp->{data}->[0] = "remoteshellexp failed sending keys to enablenodes."; - xCAT::MsgUtils->message("E", $rsp, $::CALLBACK); - - } - } - if ($disablenodes) { # node on list to setup nodetonodessh - chop $disablenodes; # remove last comma - my $rc=xCAT::RemoteShellExp->remoteshellexp("s",$::CALLBACK,"/usr/bin/ssh",$disablenodes); - if ($rc != 0) - { - $rsp->{data}->[0] = "remoteshellexp failed sending keys to disablenodes."; - xCAT::MsgUtils->message("E", $rsp, $::CALLBACK); - - } - } - } 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); - if ($rc != 0) - { - $rsp->{data}->[0] = "remoteshellexp failed sending keys."; - xCAT::MsgUtils->message("E", $rsp, $::CALLBACK); - - } - } - - # must always check to see if worked, run test - my @testnodes= split(",", $nodes[0]); - foreach my $n (@testnodes) - { - my $rc= - xCAT::RemoteShellExp->remoteshellexp("t",$::CALLBACK,"/usr/bin/ssh",$n); - if ($rc != 0) - { - push @badnodes, $n; - } - } - - if (@badnodes) - { - my $nstring = join ',', @badnodes; - $rsp->{data}->[0] = - "SSH setup failed for the following nodes: $nstring."; - xCAT::MsgUtils->message("E", $rsp, $::CALLBACK); - return @badnodes; - } - else - { - $rsp->{data}->[0] = "$::REMOTE_SHELL setup is complete."; - xCAT::MsgUtils->message("I", $rsp, $::CALLBACK); - return 0; - } -} - -#-------------------------------------------------------------------------------- - -=head3 cpSSHFiles - - Builds authorized_keyfiles for root - - Arguments: - install directory path - Returns: - - Globals: - $::CALLBACK - Error: - - Example: - xCAT::Utils->cpSSHFiles($dir); - - Comments: - none - -=cut - -#-------------------------------------------------------------------------------- - - -sub cpSSHFiles -{ - my ($class, $SSHdir) = @_; - my ($cmd, $rc); - my $rsp = {}; - if ($::VERBOSE) - { - $rsp->{data}->[0] = "Copying SSH Keys"; - xCAT::MsgUtils->message("I", $rsp, $::CALLBACK); - } - my $home = xCAT::Utils->getHomeDir("root"); - - - if (xCAT::Utils->isMN()) { # if on Management Node - if (!(-e "$home/.ssh/id_rsa.pub")) # only using rsa - { - $rsp->{data}->[0] = "Public key id_rsa.pub was missing in the .ssh directory."; - xCAT::MsgUtils->message("E", $rsp, $::CALLBACK); - return 1; - } - # copy to id_rsa public key to authorized_keys in the install directory - my $authorized_keys = "$SSHdir/authorized_keys"; - # changed from identity.pub - $cmd = " cp $home/.ssh/id_rsa.pub $authorized_keys"; - xCAT::Utils->runcmd($cmd, 0); - $rsp = {}; - if ($::RUNCMD_RC != 0) - { - $rsp->{data}->[0] = "$cmd failed.\n"; - xCAT::MsgUtils->message("E", $rsp, $::CALLBACK); - return (1); - - } - else - { - if ($::VERBOSE) - { - $rsp->{data}->[0] = "$cmd succeeded.\n"; - xCAT::MsgUtils->message("I", $rsp, $::CALLBACK); - } - } - } # end is MN - - # on MN and SN - # make tmp directory to hold authorized_keys for node transfer - if (!(-e "$home/.ssh/tmp")) { - $cmd = " mkdir $home/.ssh/tmp"; - xCAT::Utils->runcmd($cmd, 0); - $rsp = {}; - if ($::RUNCMD_RC != 0) - { - $rsp->{data}->[0] = "$cmd failed.\n"; - xCAT::MsgUtils->message("E", $rsp, $::CALLBACK); - return (1); - - } - } - # create authorized_keys file - if (xCAT::Utils->isMN()) { # if on Management Node - $cmd = " cp $home/.ssh/id_rsa.pub $home/.ssh/tmp/authorized_keys"; - } else { # SN - $cmd = " cp $home/.ssh/authorized_keys $home/.ssh/tmp/authorized_keys"; - } - xCAT::Utils->runcmd($cmd, 0); - $rsp = {}; - if ($::RUNCMD_RC != 0) - { - $rsp->{data}->[0] = "$cmd failed.\n"; - xCAT::MsgUtils->message("E", $rsp, $::CALLBACK); - return (1); - - } - else - { - chmod 0600, "$home/.ssh/tmp/authorized_keys"; - if ($::VERBOSE) - { - $rsp->{data}->[0] = "$cmd succeeded.\n"; - xCAT::MsgUtils->message("I", $rsp, $::CALLBACK); - } - } - - return (0); -} - -#-------------------------------------------------------------------------------- - -=head3 bldnonrootSSHFiles - - Builds authorized_keyfiles for the non-root id - It must not only contain the public keys for the non-root id - but also the public keys for root - - Arguments: - from_userid -current id running xdsh from the command line - Returns: - - Globals: - $::CALLBACK - Error: - - Example: - xCAT::Utils->bldnonrootSSHFiles; - - Comments: - none - -=cut - -#-------------------------------------------------------------------------------- - -sub bldnonrootSSHFiles -{ - my ($class, $from_userid) = @_; - my ($cmd, $rc); - my $rsp = {}; - if ($::VERBOSE) - { - $rsp->{data}->[0] = "Building SSH Keys for $from_userid"; - xCAT::MsgUtils->message("I", $rsp, $::CALLBACK); - } - my $home = xCAT::Utils->getHomeDir($from_userid); - # Handle non-root userid may not be in /etc/passwd maybe LDAP - if (!$home) { - $home=`su - $from_userid -c pwd`; - chop $home; - } - my $roothome = xCAT::Utils->getHomeDir("root"); - if (xCAT::Utils->isMN()) { # if on Management Node - if (!(-e "$home/.ssh/id_rsa.pub")) - { - return 1; - } - } - # make tmp directory to hold authorized_keys for node transfer - if (!(-e "$home/.ssh/tmp")) { - $cmd = " mkdir $home/.ssh/tmp"; - xCAT::Utils->runcmd($cmd, 0); - $rsp = {}; - if ($::RUNCMD_RC != 0) - { - $rsp->{data}->[0] = "$cmd failed.\n"; - xCAT::MsgUtils->message("E", $rsp, $::CALLBACK); - return (1); - - } - } - # create authorized_key file in tmp directory for transfer - if (xCAT::Utils->isMN()) { # if on Management Node - $cmd = " cp $home/.ssh/id_rsa.pub $home/.ssh/tmp/authorized_keys"; - } else { # SN - $cmd = " cp $home/.ssh/authorized_keys $home/.ssh/tmp/authorized_keys"; - } - xCAT::Utils->runcmd($cmd, 0); - $rsp = {}; - if ($::RUNCMD_RC != 0) - { - $rsp->{data}->[0] = "$cmd failed.\n"; - xCAT::MsgUtils->message("E", $rsp, $::CALLBACK); - return (1); - - } - else - { - chmod 0600, "$home/.ssh/tmp/authorized_keys"; - if ($::VERBOSE) - { - $rsp->{data}->[0] = "$cmd succeeded.\n"; - xCAT::MsgUtils->message("I", $rsp, $::CALLBACK); - } - } - if (xCAT::Utils->isMN()) { # if on Management Node - # if cannot access, warn and continue - $rsp = {}; - $cmd = "cat $roothome/.ssh/id_rsa.pub >> $home/.ssh/tmp/authorized_keys"; - xCAT::Utils->runcmd($cmd, 0); - if ($::RUNCMD_RC != 0) - { - $rsp->{data}->[0] = "Warning: Cannot give $from_userid root ssh authority. \n"; - xCAT::MsgUtils->message("I", $rsp, $::CALLBACK); - - } - else - { - if ($::VERBOSE) - { - $rsp->{data}->[0] = "$cmd succeeded.\n"; - xCAT::MsgUtils->message("I", $rsp, $::CALLBACK); - } - } - } - - - return (0); -} #------------------------------------------------------------------------------- @@ -2087,968 +1368,6 @@ sub isMN } } -#------------------------------------------------------------------------------- - -=head3 classful_networks_for_net_and_mask - - Arguments: - network and mask - Returns: - a list of classful subnets that constitute the entire potentially classless arguments - Globals: - none - Error: - none - Example: - Comments: - none -=cut - -#------------------------------------------------------------------------------- -sub classful_networks_for_net_and_mask -{ - my $network = shift; - my $mask = shift; - my $given_mask = 0; - if ($mask =~ /\./) - { - $given_mask = 1; - my $masknumber = unpack("N", inet_aton($mask)); - $mask = 32; - until ($masknumber % 2) - { - $masknumber = $masknumber >> 1; - $mask--; - } - } - - my @results; - my $bitstoeven = (8 - ($mask % 8)); - if ($bitstoeven eq 8) { $bitstoeven = 0; } - my $resultmask = $mask + $bitstoeven; - if ($given_mask) - { - $resultmask = - inet_ntoa(pack("N", (2**$resultmask - 1) << (32 - $resultmask))); - } - push @results, $resultmask; - - my $padbits = (32 - ($bitstoeven + $mask)); - my $numchars = int(($mask + $bitstoeven) / 4); - my $curmask = 2**$mask - 1 << (32 - $mask); - my $nown = unpack("N", inet_aton($network)); - $nown = $nown & $curmask; - my $highn = $nown + ((2**$bitstoeven - 1) << (32 - $mask - $bitstoeven)); - - while ($nown <= $highn) - { - push @results, inet_ntoa(pack("N", $nown)); - - #$rethash->{substr($nowhex, 0, $numchars)} = $network; - $nown += 1 << (32 - $mask - $bitstoeven); - } - return @results; -} - -#------------------------------------------------------------------------------- - -=head3 my_hexnets - - Arguments: - none - Returns: - Globals: - none - Error: - none - Example: - Comments: - none -=cut - -#------------------------------------------------------------------------------- -sub my_hexnets -{ - my $rethash; - my @nets = split /\n/, `/sbin/ip addr`; - foreach (@nets) - { - my @elems = split /\s+/; - unless (/^\s*inet\s/) - { - next; - } - (my $curnet, my $maskbits) = split /\//, $elems[2]; - my $bitstoeven = (4 - ($maskbits % 4)); - if ($bitstoeven eq 4) { $bitstoeven = 0; } - my $padbits = (32 - ($bitstoeven + $maskbits)); - my $numchars = int(($maskbits + $bitstoeven) / 4); - my $curmask = 2**$maskbits - 1 << (32 - $maskbits); - my $nown = unpack("N", inet_aton($curnet)); - $nown = $nown & $curmask; - my $highn = - $nown + ((2**$bitstoeven - 1) << (32 - $maskbits - $bitstoeven)); - - while ($nown <= $highn) - { - my $nowhex = sprintf("%08x", $nown); - $rethash->{substr($nowhex, 0, $numchars)} = $curnet; - $nown += 1 << (32 - $maskbits - $bitstoeven); - } - } - return $rethash; -} - -#------------------------------------------------------------------------------- - -=head3 get_host_from_ip - Description: - Get the hostname of an IP addresses. First from hosts table, and then try system resultion. - If there is a shortname, it will be returned. Otherwise it will return long name. If the IP cannot be resolved, return undef; - - Arguments: - $ip: the IP to get; - - Returns: - Return: the hostname. -For an example - - Globals: - none - - Error: - none - - Example: - xCAT::Utils::get_host_from_ip('192.168.200.1') - - Comments: -=cut - -#----------------------------------------------------------------------- -sub get_host_from_ip -{ - my $ip = shift; -} - -#------------------------------------------------------------------------------- - -=head3 isPingable - Description: - Check if an IP address can be pinged - - Arguments: - $ip: the IP to ping; - - Returns: - Return: 1 indicates yes; 0 indicates no. -For an example - - Globals: - none - - Error: - none - - Example: - xCAT::Utils::isPingable('192.168.200.1') - - Comments: - none -=cut - -#----------------------------------------------------------------------- -my %PING_CACHE; -sub isPingable -{ - my $ip = shift; - - my $rc; - if ( exists $PING_CACHE{ $ip}) - { - $rc = $PING_CACHE{ $ip}; - } - else - { - my $res = `LANG=C ping -c 1 -w 5 $ip 2>&1`; - if ( $res =~ /100% packet loss/g) - { - $rc = 1; - } - else - { - $rc = 0; - } - $PING_CACHE{ $ip} = $rc; - } - - return ! $rc; -} - -#------------------------------------------------------------------------------- - -=head3 my_nets - Description: - Return a hash ref that contains all subnet and netmask on the mn (or sn). This subroutine can be invoked on both Linux and AIX. - - Arguments: - none. - - Returns: - Return a hash ref. Each entry will be: =>; - For an example: - '192.168.200.0/255.255.255.0' => '192.168.200.246'; -For an example - - Globals: - none - - Error: - none - - Example: - xCAT::Utils::my_nets(). - - Comments: - none -=cut -#----------------------------------------------------------------------- -sub my_nets -{ - require xCAT::Table; - my $rethash; - my @nets; - my $v6net; - my $v6ip; - if ( $^O eq 'aix') - { - @nets = split /\n/, `/usr/sbin/ifconfig -a`; - } - else - { - @nets = split /\n/, `/sbin/ip addr`; #could use ip route, but to match hexnets... - } - foreach (@nets) - { - $v6net = ''; - my @elems = split /\s+/; - unless (/^\s*inet/) - { - next; - } - my $curnet; my $maskbits; - if ( $^O eq 'aix') - { - if ($elems[1] eq 'inet6') - { - $v6net=$elems[2]; - $v6ip=$elems[2]; - $v6ip =~ s/\/.*//; # ipv6 address 4000::99/64 - $v6ip =~ s/\%.*//; # ipv6 address ::1%1/128 - } - else - { - $curnet = $elems[2]; - $maskbits = formatNetmask( $elems[4], 2, 1); - } - } - else - { - if ($elems[1] eq 'inet6') - { - next; #Linux IPv6 TODO, do not return IPv6 networks on Linux for now - } - ($curnet, $maskbits) = split /\//, $elems[2]; - } - if (!$v6net) - { - my $curmask = 2**$maskbits - 1 << (32 - $maskbits); - my $nown = unpack("N", inet_aton($curnet)); - $nown = $nown & $curmask; - my $textnet=inet_ntoa(pack("N",$nown)); - $textnet.="/$maskbits"; - $rethash->{$textnet} = $curnet; - } - else - { - $rethash->{$v6net} = $v6ip; - } - } - - - # now get remote nets - my $nettab = xCAT::Table->new("networks"); - #my $sitetab = xCAT::Table->new("site"); - #my $master = $sitetab->getAttribs({key=>'master'},'value'); - #$master = $master->{value}; - my @masters = xCAT::Utils->get_site_attribute("master"); - my $master = $masters[0]; - my @vnets = $nettab->getAllAttribs('net','mgtifname','mask'); - - foreach(@vnets){ - my $n = $_->{net}; - my $if = $_->{mgtifname}; - my $nm = $_->{mask}; - if (!$n || !$if || $nm) - { - next; #incomplete network - } - if ($if =~ /!remote!/) { #only take in networks with special interface - $nm = formatNetmask($nm, 0 , 1); - $n .="/$nm"; - #$rethash->{$n} = $if; - $rethash->{$n} = $master; - } - } - return $rethash; -} -#------------------------------------------------------------------------------- - -=head3 my_if_netmap - Arguments: - none - Returns: - hash of networks to interface names - Globals: - none - Error: - none - Comments: - none -=cut - -#------------------------------------------------------------------------------- -sub my_if_netmap -{ - my $net; - if (scalar(@_)) - { #called with the other syntax - $net = shift; - } - my @rtable = split /\n/, `netstat -rn`; - if ($?) - { - return "Unable to run netstat, $?"; - } - my %retmap; - foreach (@rtable) - { - if (/^\D/) { next; } #skip headers - if (/^\S+\s+\S+\s+\S+\s+\S*G/) - { - next; - } #Skip networks that require gateways to get to - /^(\S+)\s.*\s(\S+)$/; - $retmap{$1} = $2; - } - return \%retmap; -} - -#------------------------------------------------------------------------------- - -=head3 my_ip_facing - Returns my ip address - Linux only - Arguments: - nodename - Returns: - Globals: - none - Error: - none - Example: - Comments: - none -=cut - -#------------------------------------------------------------------------------- -sub my_ip_facing -{ - my $peer = shift; - if (@_) - { - $peer = shift; - } - return my_ip_facing_aix( $peer) if ( $^O eq 'aix'); - my $peernumber = inet_aton($peer); #TODO: IPv6 support - unless ($peernumber) { return undef; } - my $noden = unpack("N", inet_aton($peer)); - my @nets = split /\n/, `/sbin/ip addr`; - foreach (@nets) - { - my @elems = split /\s+/; - unless (/^\s*inet\s/) - { - next; - } - (my $curnet, my $maskbits) = split /\//, $elems[2]; - my $curmask = 2**$maskbits - 1 << (32 - $maskbits); - my $curn = unpack("N", inet_aton($curnet)); - if (($noden & $curmask) == ($curn & $curmask)) - { - return $curnet; - } - } - return undef; -} - -#------------------------------------------------------------------------------- - -=head3 my_ip_facing_aix - Returns my ip address - AIX only - Arguments: - nodename - Returns: - Globals: - none - Error: - none - Example: - Comments: - none -=cut - -#------------------------------------------------------------------------------- -sub my_ip_facing_aix -{ - my $peer = shift; - my @nets = `ifconfig -a`; - chomp @nets; - foreach my $net (@nets) - { - my ($curnet,$netmask); - if ( $net =~ /^\s*inet\s+([\d\.]+)\s+netmask\s+(\w+)\s+broadcast/) - { - ($curnet,$netmask) = ($1,$2); - } - elsif ($net =~ /^\s*inet6\s+(.*)$/) - { - ($curnet,$netmask) = split('/', $1); - } - else - { - next; - } - if (isInSameSubnet($peer, $curnet, $netmask, 2)) - { - return $curnet; - } - } - return undef; -} - -#------------------------------------------------------------------------------- - -=head3 formatNetmask - Description: - Transform netmask to one of 3 formats (255.255.255.0, 24, 0xffffff00). - - Arguments: - $netmask: the original netmask - $origType: the original netmask type. The valid value can be 0, 1, 2: - Type 0: 255.255.255.0 - Type 1: 24 - Type 2: 0xffffff00 - $newType: the new netmask type, valid values can be 0,1,2, as above. - - Returns: - Return undef if any error. Otherwise return the netmask in new format. - - Globals: - none - - Error: - none - - Example: - xCAT::Utils::formatNetmask( '24', 1, 0); #return '255.255.255.0'. - - Comments: - none -=cut -#----------------------------------------------------------------------- -sub formatNetmask -{ - my $mask = shift; - my $origType = shift; - my $newType = shift; - my $maskn; - if ( $origType == 0) - { - $maskn = unpack("N", inet_aton($mask)); - } - elsif ( $origType == 1) - { - $maskn = 2**$mask - 1 << (32 - $mask); - } - elsif( $origType == 2) - { - $maskn = hex $mask; - } - else - { - return undef; - } - - if ( $newType == 0) - { - return inet_ntoa( pack('N', $maskn)); - } - if ( $newType == 1) - { - my $bin = unpack ("B32", pack("N", $maskn)); - my @dup = ( $bin =~ /(1{1})0*/g); - return scalar ( @dup); - } - if ( $newType == 2) - { - return sprintf "0x%1x", $maskn; - } - return undef; -} - -#------------------------------------------------------------------------------- - -=head3 isInSameSubnet - Description: - Check if 2 given IP addresses are in same subnet - - Arguments: - $ip1: the first IP - $ip2: the second IP - $mask: the netmask, here are 3 possible netmask types, following are examples for these 3 types: - Type 0: 255.255.255.0 - Type 1: 24 - Type 2: 0xffffff00 - $masktype: the netmask type, 3 possible values: 0,1,2, as indicated above - - Returns: - 1: they are in same subnet - 2: not in same subnet - - Globals: - none - - Error: - none - - Example: - xCAT::Utils::isInSameSubnet( '192.168.10.1', '192.168.10.2', '255.255.255.0', 0); - - Comments: - none -=cut -#----------------------------------------------------------------------- -sub isInSameSubnet -{ - my $ip1 = shift; - my $ip2 = shift; - my $mask = shift; - my $maskType = shift; - - $ip1 = xCAT::NetworkUtils->getipaddr($ip1); - $ip2 = xCAT::NetworkUtils->getipaddr($ip2); - - if (!defined($ip1) || !defined($ip2)) - { - return undef; - } - - if ((($ip1 =~ /\d+\.\d+\.\d+\.\d+/) && ($ip2 !~ /\d+\.\d+\.\d+\.\d+/)) - ||(($ip1 !~ /\d+\.\d+\.\d+\.\d+/) && ($ip2 =~ /\d+\.\d+\.\d+\.\d+/))) - { - #ipv4 and ipv6 can not be in the same subnet - return undef; - } - - if (($ip1 =~ /\d+\.\d+\.\d+\.\d+/) && ($ip2 =~ /\d+\.\d+\.\d+\.\d+/)) - { - my $maskn; - if ( $maskType == 0) - { - $maskn = unpack("N", inet_aton($mask)); - } - elsif ( $maskType == 1) - { - $maskn = 2**$mask - 1 << (32 - $mask); - } - elsif( $maskType == 2) - { - $maskn = hex $mask; - } - else - { - return undef; - } - - my $ip1n = unpack("N", inet_aton($ip1)); - my $ip2n = unpack("N", inet_aton($ip2)); - - return ( ( $ip1n & $maskn) == ( $ip2n & $maskn) ); - } - else - { - #ipv6 - if (($ip1 =~ /\%/) || ($ip2 =~ /\%/)) - { - return undef; - } - my $netipmodule = eval {require Net::IP;}; - if ($netipmodule) { - my $eip1 = Net::IP::ip_expand_address ($ip1,6); - my $eip2 = Net::IP::ip_expand_address ($ip2,6); - my $bmask = Net::IP::ip_get_mask($mask,6); - my $bip1 = Net::IP::ip_iptobin($eip1,6); - my $bip2 = Net::IP::ip_iptobin($eip2,6); - if (($bip1 & $bmask) == ($bip2 & $bmask)) { - return 1; - } - } # else, can not check without Net::IP module - return undef; - } -} -#------------------------------------------------------------------------------- - -=head3 nodeonmynet - checks to see if node is on any network this server is attached to or remote network potentially managed by this system - Arguments: - Node name - Returns: 1 if node is on the network - Globals: - none - Error: - none - Example: - Comments: - none -=cut - -#------------------------------------------------------------------------------- - -sub nodeonmynet -{ - require xCAT::Table; - my $nodetocheck = shift; - if (scalar(@_)) - { - $nodetocheck = shift; - } - - my $nodeip = getNodeIPaddress( $nodetocheck ); - if (!$nodeip) - { - return 0; - } - unless ($nodeip =~ /\d+\.\d+\.\d+\.\d+/) - { - #IPv6 - if ( $^O eq 'aix') - { - my @subnets = get_subnet_aix(); - for my $net_ent (@subnets) - { - if ($net_ent !~ /-/) - { - #ipv4 - next; - } - my ($net, $interface, $mask, $flag) = split/-/ , $net_ent; - if (xCAT::NetworkUtils->ishostinsubnet($nodeip, $mask, $net)) - { - return 1; - } - } - - } else { - my @v6routes = split /\n/,`ip -6 route`; - foreach (@v6routes) { - if (/via/ or /^unreachable/ or /^fe80::\/64/) { - #only count local ones, remote ones can be caught in next loop - #also, link-local would be a pitfall, - #since more context than address is - #needed to determine locality - next; - } - s/ .*//; #remove all after the space - if (xCAT::NetworkUtils->ishostinsubnet($nodeip,'',$_)) { #bank on CIDR support - return 1; - } - } - } - my $nettab=xCAT::Table->new("networks"); - my @vnets = $nettab->getAllAttribs('net','mgtifname','mask'); - foreach (@vnets) { - if ((defined $_->{mgtifname}) && ($_->{mgtifname} eq '!remote!')) - { - if (xCAT::NetworkUtils->ishostinsubnet($nodeip, $_->{mask}, $_->{net})) - { - return 1; - } - } - } - return 0; - } - my $noden = unpack("N", inet_aton($nodeip)); - my @nets; - if ($utildata->{nodeonmynetdata} and $utildata->{nodeonmynetdata}->{pid} == $$) { - @nets = @{$utildata->{nodeonmynetdata}->{nets}}; - } else { - if ( $^O eq 'aix') - { - my @subnets = get_subnet_aix(); - for my $net_ent (@subnets) - { - if ($net_ent =~ /-/) - { - #ipv6 - next; - } - my @ents = split /:/ , $net_ent; - push @nets, $ents[0] . '/' . $ents[2] . ' dev ' . $ents[1]; - } - - } - else - { - @nets = split /\n/, `/sbin/ip route`; - } - my $nettab=xCAT::Table->new("networks"); - my @vnets = $nettab->getAllAttribs('net','mgtifname','mask'); - foreach (@vnets) { - if ((defined $_->{mgtifname}) && ($_->{mgtifname} eq '!remote!')) - { #global scoped network - my $curm = unpack("N", inet_aton($_->{mask})); - my $bits=32; - until ($curm & 1) { - $bits--; - $curm=$curm>>1; - } - push @nets,$_->{'net'}."/".$bits." dev remote"; - } - } - $utildata->{nodeonmynetdata}->{pid}=$$; - $utildata->{nodeonmynetdata}->{nets} = \@nets; - } - foreach (@nets) - { - my @elems = split /\s+/; - unless ($elems[1] =~ /dev/) - { - next; - } - (my $curnet, my $maskbits) = split /\//, $elems[0]; - my $curmask = 2**$maskbits - 1 << (32 - $maskbits); - my $curn = unpack("N", inet_aton($curnet)); - if (($noden & $curmask) == $curn) - { - return 1; - } - } - return 0; -} - -#------------------------------------------------------------------------------- - -=head3 getNodeIPaddress - Arguments: - Node name only one at a time - Returns: ip address(s) - Globals: - none - Error: - none - Example: my $c1 = xCAT::Utils::getNodeIPaddress($nodetocheck); - -=cut - -#------------------------------------------------------------------------------- - -sub getNodeIPaddress -{ - require xCAT::Table; - my $nodetocheck = shift; - my $port = shift; - my $nodeip; - - $nodeip = xCAT::NetworkUtils->getipaddr($nodetocheck); - if (!$nodeip) - { - my $hoststab = xCAT::Table->new( 'hosts'); - my $ent = $hoststab->getNodeAttribs( $nodetocheck, ['ip'] ); - if ( $ent->{'ip'} ) { - $nodeip = $ent->{'ip'}; - } - } - - if ( $nodeip ) { - return $nodeip; - } else { - return undef; - } -} - - - -#------------------------------------------------------------------------------- - -=head3 thishostisnot - returns 0 if host is not the same - Arguments: - hostname - Returns: - Globals: - none - Error: - none - Example: - Comments: - none -=cut - -#------------------------------------------------------------------------------- - -sub thishostisnot -{ - my $comparison = shift; - if (scalar(@_)) - { - $comparison = shift; - } - - my @ips; - if ( $^O eq 'aix') - { - @ips = split /\n/, `/usr/sbin/ifconfig -a`; - } - else - { - @ips = split /\n/, `/sbin/ip addr`; - } - my $comp = xCAT::NetworkUtils->getipaddr($comparison); - if ($comp) - { - foreach (@ips) - { - if (/^\s*inet.?\s+/) - { - my @ents = split(/\s+/); - my $ip = $ents[2]; - $ip =~ s/\/.*//; - $ip =~ s/\%.*//; - if ($ip eq $comp) - { - return 0; - } - } - } - } - return 1; -} - -#------------------------------------------------------------------------------- - -=head3 GetMasterNodeName - Reads the database for the Master node name for the input node - Arguments: - Node - Returns: - MasterHostName - Globals: - none - Error: - none - Example: - $master=(xCAT::Utils->GetMasterNodeName($node)) - Comments: - none -=cut - -#------------------------------------------------------------------------------- -sub GetMasterNodeName -{ - require xCAT::Table; - my ($class, $node) = @_; - my $master; - my $noderestab = xCAT::Table->new('noderes'); - my $typetab = xCAT::Table->new('nodetype'); - unless ($noderestab and $typetab) - { - xCAT::MsgUtils->message('S', - "Unable to open noderes or nodetype table.\n"); - return 1; - } - #my $sitetab = xCAT::Table->new('site'); - #(my $et) = $sitetab->getAttribs({key => "master"}, 'value'); - #if ($et and $et->{value}) - #{ - # $master = $et->{value}; - #} - my @masters = xCAT::Utils->get_site_attribute("master"); - $master = $masters[0]; - - my $et = $noderestab->getNodeAttribs($node, ['xcatmaster']); - if ($et and $et->{'xcatmaster'}) - { - $master = $et->{'xcatmaster'}; - } - unless ($master) - { - xCAT::MsgUtils->message('S', "Unable to identify master for $node.\n"); - #$sitetab->close; - $noderestab->close; - $typetab->close; - return 1; - } - - #$sitetab->close; - $noderestab->close; - $typetab->close; - return $master; -} - -#------------------------------------------------------------------------------- - -=head3 GetNodeOSARCH - Reads the database for the OS and Arch of the input Node - Arguments: - Node - Returns: - $et->{'os'} - $et->{'arch'} - Globals: - none - Error: - none - Example: - $master=(xCAT::Utils->GetNodeOSARCH($node)) - Comments: - none -=cut - -#------------------------------------------------------------------------------- -sub GetNodeOSARCH -{ - require xCAT::Table; - my ($class, $node) = @_; - my $noderestab = xCAT::Table->new('noderes'); - my $typetab = xCAT::Table->new('nodetype'); - unless ($noderestab and $typetab) - { - xCAT::MsgUtils->message('S', - "Unable to open noderes or nodetype table.\n"); - return 1; - } - my $et = $typetab->getNodeAttribs($node, ['os', 'arch']); - unless ($et and $et->{'os'} and $et->{'arch'}) - { - xCAT::MsgUtils->message('S', - "No os/arch setting in nodetype table for $node.\n"); - return 1; - } - - return $et; - -} #----------------------------------------------------------------------------- @@ -3088,204 +1407,6 @@ sub exportDBConfig #----------------------------------------------------------------------------- -=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 -=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::Utils->GetMasterNodeName($nodename); - if (!($masternode)) - { - xCAT::MsgUtils->message('S', - "Could not get Master for node $nodename\n"); - return 1; - } - - $et = xCAT::Utils->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::Utils->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 determinehostname and ip address(s) - - Used on the service node to figure out what hostname and ip address(s) - are valid names and addresses - Input: None - Output: ipaddress(s),nodename -=cut - -#----------------------------------------------------------------------------- -sub determinehostname -{ - my $hostname; - my $hostnamecmd = "/bin/hostname"; - my @thostname = xCAT::Utils->runcmd($hostnamecmd, 0); - if ($::RUNCMD_RC != 0) - { # could not get hostname - xCAT::MsgUtils->message("S", - "Error $::RUNCMD_RC from $hostnamecmd command\n"); - exit $::RUNCMD_RC; - } - $hostname = $thostname[0]; - - #get all potentially valid abbreviations, and pick the one that is ok - #by 'noderange' - my @hostnamecandidates; - my $nodename; - while ($hostname =~ /\./) { - push @hostnamecandidates,$hostname; - $hostname =~ s/\.[^\.]*//; - } - push @hostnamecandidates,$hostname; - my $checkhostnames = join(',',@hostnamecandidates); - my @validnodenames = xCAT::NodeRange::noderange($checkhostnames); - unless (scalar @validnodenames) { #If the node in question is not in table, take output literrally. - push @validnodenames,$hostnamecandidates[0]; - } - #now, noderange doesn't guarantee the order, so we search the preference order, most to least specific. - foreach my $host (@hostnamecandidates) { - if (grep /^$host$/,@validnodenames) { - $nodename = $host; - last; - } - } - my @ips = xCAT::Utils->gethost_ips; - my @hostinfo = (@ips, $nodename); - - return @hostinfo; -} - -#----------------------------------------------------------------------------- - =head3 update_xCATSN Will add the input service string to /etc/xCATSN to indicate that the service has been setup by the service node @@ -3315,559 +1436,6 @@ sub update_xCATSN #----------------------------------------------------------------------------- -=head3 gethost_ips (AIX and Linux) - Will use ifconfig to determine all possible ip addresses for the - host it is running on and then gethostbyaddr to get all possible hostnames - - input: - output: array of ipaddress(s) and hostnames - example: @ips=xCAT::gethost_ips(); - -=cut - -#----------------------------------------------------------------------------- -sub gethost_ips -{ - my ($class) = @_; - my $cmd; - my @ipaddress; - $cmd = "ifconfig" . " -a"; - $cmd = $cmd . "| grep \"inet\""; - my @result = xCAT::Utils->runcmd($cmd, 0); - if ($::RUNCMD_RC != 0) - { - xCAT::MsgUtils->message("S", "Error from $cmd\n"); - exit $::RUNCMD_RC; - } - foreach my $addr (@result) - { - my @ip; - if (xCAT::Utils->isLinux()) - { - if ($addr =~ /inet6/) - { - #TODO, Linux ipv6 - } - else - { - my ($inet, $addr1, $Bcast, $Mask) = split(" ", $addr); - @ip = split(":", $addr1); - push @ipaddress, $ip[1]; - } - } - else - { #AIX - if ($addr =~ /inet6/) - { - $addr =~ /\s*inet6\s+([\da-fA-F:]+).*\/(\d+)/; - my $v6ip = $1; - my $v6mask = $2; - if ($v6ip) - { - push @ipaddress, $v6ip; - } - } - else - { - my ($inet, $addr1, $netmask, $mask1, $Bcast, $bcastaddr) = - split(" ", $addr); - push @ipaddress, $addr1; - } - - } - } - my @names = @ipaddress; - foreach my $ipaddr (@names) - { - my $hostname = xCAT::NetworkUtils->gethostname($ipaddr); - if ($hostname) - { - my @shorthost = split(/\./, $hostname); - push @ipaddress, $shorthost[0]; - } - } - - return @ipaddress; -} - -#----------------------------------------------------------------------------- - -=head3 create_postscripts_tar - - This routine will tar and compress the /install/postscripts directory - and place in /install/autoinst/xcat_postscripts.Z - - input: none - output: - example: $rc=xCAT::create_postscripts_tar(); - -=cut - -#----------------------------------------------------------------------------- -sub create_postscripts_tar -{ - my ($class) = @_; - my $installdir = getInstallDir(); - my $cmd; - if (!(-e "$installdir/autoinst")) - { - mkdir("$installdir/autoinst"); - } - - $cmd = - "cd $installdir/postscripts; tar -cf $installdir/autoinst/xcatpost.tar * .ssh/* _xcat/*; gzip -f $installdir/autoinst/xcatpost.tar"; - my @result = xCAT::Utils->runcmd($cmd, 0); - if ($::RUNCMD_RC != 0) - { - xCAT::MsgUtils->message("S", "Error from $cmd\n"); - return $::RUNCMD_RC; - } - - # for AIX add an entry to the /etc/tftpaccess.ctrl file so - # we can tftp the tar file from the node - if (xCAT::Utils->isAIX()) - { - my $tftpctlfile = "/etc/tftpaccess.ctl"; - my $entry = "allow:$installdir/autoinst/xcatpost.tar.gz"; - - # see if there is already an entry - my $cmd = "cat $tftpctlfile | grep xcatpost"; - my @result = xCAT::Utils->runcmd("$cmd", -1); - if ($::RUNCMD_RC != 0) - { - - # not found so add it - unless (open(TFTPFILE, ">>$tftpctlfile")) - { - xCAT::MsgUtils->message("S", "Could not open $tftpctlfile.\n"); - return $::RUNCMD_RC; - } - - print TFTPFILE $entry; - - close(TFTPFILE); - } - } - return 0; -} - -#----------------------------------------------------------------------------- - -=head3 get_site_Master - - Reads the site table for the Master attribute and returns it. - input: none - output : value of site.Master attribute , blank is an error - example: $Master =xCAT::get_site_Master(); - -=cut - -#----------------------------------------------------------------------------- - -sub get_site_Master -{ - if ($::XCATSITEVALS{master}) { - return $::XCATSITEVALS{master}; - } - require xCAT::Table; - my $Master; - my $sitetab = xCAT::Table->new('site'); - (my $et) = $sitetab->getAttribs({key => "master"}, 'value'); - if ($et and $et->{value}) - { - $Master = $et->{value}; - } - else - { -# this msg can be missleading -# xCAT::MsgUtils->message('E', -# "Unable to read site table for Master attribute.\n"); - } - return $Master; -} - -#----------------------------------------------------------------------------- - -=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::Utils->get_ServiceNode(\@nodes,$service,"MN"); - $sn =xCAT::Utils->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::Utils->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::Utils->getSNformattedhash(\@nodes,$service,"MN", $type); - $sn =xCAT::Utils->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::Utils->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 toIP - - IPv4 function to convert hostname to IP address - -=cut - -#----------------------------------------------------------------------------- -sub toIP -{ - - if (($_[0] =~ /^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$/) || ($_[0] =~ /:/)) - { - return ([0, $_[0]]); - } - my $ip = xCAT::NetworkUtils->getipaddr($_[0]); - if (!$ip) - { - return ([1, "Cannot Resolve: $_[0]\n"]); - } - return ([0, $ip]); -} - -#----------------------------------------------------------------------------- - =head3 isSN Determines if the input node name is a service node @@ -3919,213 +1487,6 @@ sub isSN return 0; } -#----------------------------------------------------------------------------- - -=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::Utils->get_AllSN - 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::Utils->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::Utils->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::Utils->getSNList($servicename) { blah; } - $sn= xCAT::Utils->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 validate_ip - Validate list of IPs - Arguments: - List of IPs - Returns: - 1 - Invalid IP address in the list - 0 - IP addresses are all valid - Globals: - none - Error: - none - Example: - if (xCAT::Utils->validate_ip($IP)) {} - Comments: - none -=cut - -#------------------------------------------------------------------------------- -sub validate_ip -{ - my ($class, @IPs) = @_; - foreach (@IPs) { - my $ip = $_; - #TODO need more check for IPv6 address - if ($ip =~ /:/) - { - return([0]); - } - ################################### - # Length is 4 for IPv4 addresses - ################################### - my (@octets) = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/; - if ( scalar(@octets) != 4 ) { - return( [1,"Invalid IP address1: $ip"] ); - } - foreach my $octet ( @octets ) { - if (( $octet < 0 ) or ( $octet > 255 )) { - return( [1,"Invalid IP address2: $ip"] ); - } - } - } - return([0]); -} - #------------------------------------------------------------------------------- =head3 isMounted @@ -4295,137 +1656,6 @@ sub get_image_name #------------------------------------------------------------------------------- -=head3 logEventsToDatabase - Logs the given events info to the xCAT's 'eventlog' database - Arguments: - arrayref -- A pointer to an array. Each element is a hash that contains an events. - The hash should contain the at least one of the following keys: - eventtime -- The format is "yyyy-mm-dd hh:mm:ss". - If omitted, the current date and time will be used. - monitor -- The name of the monitor that monitors this event. - monnode -- The node that monitors this event. - node -- The node where the event occurred. - application -- The application that reports the event. - component -- The component where the event occurred. - id -- The location or the resource name where the event occurred. - severity -- The severity of the event. Valid values are: informational, warning, critical. - message -- The full description of the event. - rawdata -- The data that associated with the event. - Returns: - (ret code, error message) - Example: - my @a=(); - my $event={ - eventtime=>"2009-07-28 23:02:03", - node => 'node1', - rawdata => 'kjdlkfajlfjdlksaj', - }; - push (@a, $event); - - my $event1={ - node => 'cu03cp', - monnode => 'cu03sv', - application => 'RMC', - component => 'IBM.Sensor', - id => 'AIXErrorLogSensor', - severity => 'warning', - }; - push(@a, $event1); - xCAT::Utils->logEventsToDatabase(\@a); - -=cut - -#------------------------------------------------------------------------------- -sub logEventsToDatabase -{ - require xCAT::Table; - my $pEvents = shift; - if (($pEvents) && ($pEvents =~ /xCAT::Utils/)) - { - $pEvents = shift; - } - - if (($pEvents) && (@$pEvents > 0)) - { - my $currtime; - my $tab = xCAT::Table->new("eventlog", -create => 1, -autocommit => 0); - if (!$tab) - { - return (1, "The evnetlog table cannot be opened."); - } - - foreach my $event (@$pEvents) - { - - #create event time if it does not exist - if (!exists($event->{eventtime})) - { - if (!$currtime) - { - my ( - $sec, $min, $hour, $mday, $mon, - $year, $wday, $yday, $isdst - ) - = localtime(time); - $currtime = sprintf("%04d-%02d-%02d %02d:%02d:%02d", - $year + 1900, $mon + 1, $mday, - $hour, $min, $sec); - } - $event->{eventtime} = $currtime; - } - my @ret = $tab->setAttribs(undef, $event); - if (@ret > 1) { return (1, $ret[1]); } - } - $tab->commit; - } - - return (0, ""); -} - - -#------------------------------------------------------------------------------- - -=head3 logEventsToTealDatabase - Logs the given events info to the TEAL's 'x_tealeventlog' database - Arguments: - arrayref -- A pointer to an array. Each element is a hash that contains an events. - Returns: - (ret code, error message) - -=cut - -#------------------------------------------------------------------------------- -sub logEventsToTealDatabase -{ - require xCAT::Table; - my $pEvents = shift; - if (($pEvents) && ($pEvents =~ /xCAT::Utils/)) - { - $pEvents = shift; - } - - if (($pEvents) && (@$pEvents > 0)) - { - my $currtime; - my $tab = xCAT::Table->new("x_tealeventlog", -create => 1, -autocommit => 0); - if (!$tab) - { - return (1, "The x_tealeventlog table cannot be opened."); - } - - foreach my $event (@$pEvents) - { - my @ret = $tab->setAttribs(undef, $event); - if (@ret > 1) { return (1, $ret[1]); } - } - $tab->commit; - } - - return (0, ""); -} - -#------------------------------------------------------------------------------- - =head3 StartService Supports AIX and Linux as long as the service is registered with lssrc or startsrc. @@ -4675,101 +1905,6 @@ sub CheckVersion #------------------------------------------------------------------------------- -=head3 getFacingIP - Gets the ip address of the adapter of the localhost that is facing the - the given node. - Assume it is the same as my_ip_facing... - Arguments: - The name of the node that is facing the localhost. - Returns: - The ip address of the adapter that faces the node. - -=cut - -#------------------------------------------------------------------------------- -sub getFacingIP -{ - my ($class, $node) = @_; - my $ip; - my $cmd; - my @ipaddress; - - my $nodeip = inet_ntoa(inet_aton($node)); - unless ($nodeip =~ /\d+\.\d+\.\d+\.\d+/) - { - return 0; #Not supporting IPv6 here IPV6TODO - } - - $cmd = "ifconfig" . " -a"; - $cmd = $cmd . "| grep \"inet \""; - my @result = xCAT::Utils->runcmd($cmd, 0); - if ($::RUNCMD_RC != 0) - { - xCAT::MsgUtils->message("S", "Error from $cmd\n"); - exit $::RUNCMD_RC; - } - - # split node address - my ($n1, $n2, $n3, $n4) = split('\.', $nodeip); - - foreach my $addr (@result) - { - my $ip; - my $mask; - if (xCAT::Utils->isLinux()) - { - my ($inet, $addr1, $Bcast, $Mask) = split(" ", $addr); - if ((!$addr1) || (!$Mask)) { next; } - my @ips = split(":", $addr1); - my @masks = split(":", $Mask); - $ip = $ips[1]; - $mask = $masks[1]; - } - else - { #AIX - my ($inet, $addr1, $netmask, $mask1, $Bcast, $bcastaddr) = - split(" ", $addr); - if ((!$addr1) && (!$mask1)) { next; } - $ip = $addr1; - $mask1 =~ s/0x//; - $mask = - `printf "%d.%d.%d.%d" \$(echo "$mask1" | sed 's/../0x& /g')`; - } - - if ($ip && $mask) - { - - # split interface IP - my ($h1, $h2, $h3, $h4) = split('\.', $ip); - - # split mask - my ($m1, $m2, $m3, $m4) = split('\.', $mask); - - # AND this interface IP with the netmask of the network - my $a1 = ((int $h1) & (int $m1)); - my $a2 = ((int $h2) & (int $m2)); - my $a3 = ((int $h3) & (int $m3)); - my $a4 = ((int $h4) & (int $m4)); - - # AND node IP with the netmask of the network - my $b1 = ((int $n1) & (int $m1)); - my $b2 = ((int $n2) & (int $m2)); - my $b3 = ((int $n3) & (int $m3)); - my $b4 = ((int $n4) & (int $m4)); - - if (($b1 == $a1) && ($b2 == $a2) && ($b3 == $a3) && ($b4 == $a4)) - { - return $ip; - } - } - } - - xCAT::MsgUtils->message("S", "Cannot find master for the node $node\n"); - return 0; -} - -#------------------------------------------------------------------------------- - =head3 osver Returns the os and version of the System you are running on Arguments: @@ -4872,227 +2007,6 @@ sub osver return ($os); } -#------------------------------------------------------------------------------- - -=head3 checkCredFiles - Checks the various credential files on the Management Node to - make sure the permission are correct for using and transferring - to the nodes and service nodes. - Also removes /install/postscripts/etc/xcat/cfgloc if found - Arguments: - $callback - Returns: - 0 - ok - Globals: - none - Error: - warnings of possible missing files and directories - Example: - my $rc=xCAT::Utils->checkCreds - Comments: - none - -=cut - -#------------------------------------------------------------------------------- -sub checkCredFiles -{ - my $lib = shift; - my $cb = shift; - my $installdir = getInstallDir(); - my $dir = "$installdir/postscripts/_xcat"; - if (-d $dir) - { - my $file = "$dir/ca.pem"; - if (-e $file) - { - - my $cmd = "/bin/chmod 0644 $file"; - my $outref = xCAT::Utils->runcmd("$cmd", 0); - if ($::RUNCMD_RC != 0) - { - my $rsp = {}; - $rsp->{data}->[0] = "Error on command: $cmd"; - xCAT::MsgUtils->message("I", $rsp, $cb); - - } - } - else - { # ca.pem missing - my $rsp = {}; - $rsp->{data}->[0] = "Error: $file is missing. Run xcatconfig (no force)"; - xCAT::MsgUtils->message("I", $rsp, $cb); - } - } - else - { - my $rsp = {}; - $rsp->{data}->[0] = "Error: $dir is missing."; - xCAT::MsgUtils->message("I", $rsp, $cb); - } - - - $dir = "$installdir/postscripts/ca"; - if (-d $dir) - { - my $file = "$dir/ca-cert.pem"; - if (-e $file) - { - - my $cmd = "/bin/chmod 0644 $file"; - my $outref = xCAT::Utils->runcmd("$cmd", 0); - if ($::RUNCMD_RC != 0) - { - my $rsp = {}; - $rsp->{data}->[0] = "Error on command: $cmd"; - xCAT::MsgUtils->message("I", $rsp, $cb); - - } - } - else - { # ca_cert.pem missing - my $rsp = {}; - $rsp->{data}->[0] = "Error: $file is missing. Run xcatconfig (no force)"; - xCAT::MsgUtils->message("I", $rsp, $cb); - } - } - else - { - my $rsp = {}; - $rsp->{data}->[0] = "Error: $dir is missing."; - xCAT::MsgUtils->message("I", $rsp, $cb); - } - - - # ssh hostkeys - $dir = "$installdir/postscripts/hostkeys"; - if (-d $dir) - { - my $file = "$dir/ssh_host_key.pub"; - if (-e $file) - { - my $file2 = "$dir/*.pub"; # all public keys - my $cmd = "/bin/chmod 0644 $file2"; - my $outref = xCAT::Utils->runcmd("$cmd", 0); - if ($::RUNCMD_RC != 0) - { - my $rsp = {}; - $rsp->{data}->[0] = "Error on command: $cmd"; - xCAT::MsgUtils->message("I", $rsp, $cb); - - } - } - else - { # hostkey missing - my $rsp = {}; - $rsp->{data}->[0] = "Error: $file is missing. Run xcatconfig (no force)"; - xCAT::MsgUtils->message("I", $rsp, $cb); - } - } - else - { - my $rsp = {}; - $rsp->{data}->[0] = "Error: $dir is missing."; - xCAT::MsgUtils->message("I", $rsp, $cb); - } - # ssh hostkeys - $dir = "/etc/xcat/hostkeys"; - if (-d $dir) - { - my $file = "$dir/ssh_host_key.pub"; - if (-e $file) - { - my $file2 = "$dir/*.pub"; # all public keys - my $cmd = "/bin/chmod 0644 $file2"; - my $outref = xCAT::Utils->runcmd("$cmd", 0); - if ($::RUNCMD_RC != 0) - { - my $rsp = {}; - $rsp->{data}->[0] = "Error on command: $cmd"; - xCAT::MsgUtils->message("I", $rsp, $cb); - - } - } - else - { # hostkey missing - my $rsp = {}; - $rsp->{data}->[0] = "Error: $file is missing. Run xcatconfig (no force)"; - xCAT::MsgUtils->message("I", $rsp, $cb); - } - } - else - { - my $rsp = {}; - $rsp->{data}->[0] = "Error: $dir is missing."; - xCAT::MsgUtils->message("I", $rsp, $cb); - } - - # ssh directory - $dir = "$installdir/postscripts/_ssh"; - - if (-d $dir) - { - my $file = "$dir/authorized_keys"; - if (-e $file) - { - my $file2 = "$dir/authorized_keys*"; - my $cmd = "/bin/chmod 0644 $file2"; - my $outref = xCAT::Utils->runcmd("$cmd", 0); - if ($::RUNCMD_RC != 0) - { - my $rsp = {}; - $rsp->{data}->[0] = "Error on command: $cmd"; - xCAT::MsgUtils->message("I", $rsp, $cb); - - } - - # make install script executable - $file2 = "$dir/copy.sh"; - if (-e $file2) - { - my $cmd = "/bin/chmod 0744 $file2"; - my $outref = xCAT::Utils->runcmd("$cmd", 0); - if ($::RUNCMD_RC != 0) - { - my $rsp = {}; - $rsp->{data}->[0] = "Error on command: $cmd"; - xCAT::MsgUtils->message("I", $rsp, $cb); - - } - } - } - else - { # authorized keys missing - my $rsp = {}; - $rsp->{data}->[0] = "Error: $file is missing. Run xcatconfig (no force)"; - xCAT::MsgUtils->message("I", $rsp, $cb); - } - } - else - { - my $rsp = {}; - $rsp->{data}->[0] = "Error: $dir is missing."; - xCAT::MsgUtils->message("I", $rsp, $cb); - } - - # remove any old cfgloc files - my $file = "$installdir/postscripts/etc/xcat/cfgloc"; - if (-e $file) - { - - my $cmd = "/bin/rm $file"; - my $outref = xCAT::Utils->runcmd("$cmd", 0); - if ($::RUNCMD_RC != 0) - { - my $rsp = {}; - $rsp->{data}->[0] = "Error on command: $cmd"; - xCAT::MsgUtils->message("I", $rsp, $cb); - - } - } - -} - #----------------------------------------------------------------------------- =head3 acquire_lock Get a lock on an arbirtrary named resource. For now, this is only across the scope of one service node/master node, an argument may be added later if/when 'global' locks are supported. This call will block until the lock is free. @@ -5132,60 +2046,6 @@ sub release_lock { close($tlock->{fd}); } - -#----------------------------------------------------------------------------- - - -=head3 getrootimage - Get the directory of root image for a node; - Note: This subroutine only works for diskless node - - Arguments: - $node - Returns: - string - directory of the root image - undef - this is not a diskless node or the root image does not existed - Globals: - none - Error: - Example: - my $node_syncfile=xCAT::Utils->getrootimage($node); - -=cut - -#----------------------------------------------------------------------------- - -sub getrootimage() -{ - require xCAT::Table; - my $node = shift; - my $installdir = getInstallDir(); - if (($node) && ($node =~ /xCAT::Utils/)) - { - $node = shift; - } - # get the os,arch,profile attributes for the nodes - my $nodetype_t = xCAT::Table->new('nodetype'); - unless ($nodetype_t) { - return ; - } - my $nodetype_v = $nodetype_t->getNodeAttribs($node, ['profile','os','arch']); - my $profile = $nodetype_v->{'profile'}; - my $os = $nodetype_v->{'os'}; - my $arch = $nodetype_v->{'arch'}; - - if ($^O eq "linux") { - my $rootdir = "$installdir/netboot/$os/$arch/$profile/rootimg/"; - if (-d $rootdir) { - return $rootdir; - } else { - return undef; - } - } else { - # For AIX - } -} - #---------------------------------------------------------------------------- =head3 parse_selection_string @@ -5601,151 +2461,9 @@ sub monitor_installation() } return $monsettings; } -#------------------------------------------------------------------------------- -=head3 get_subnet_aix - Description: - To get present subnet configuration by parsing the output of 'netstat'. Only designed for AIX. - Arguments: - None - Returns: - @aix_nrn : An array with entries in format "net:nic:netmask:flag". Following is an example entry: - 9.114.47.224:en0:27:U - Globals: - none - Error: - none - Example: - my @nrn =xCAT::Utils::get_subnet_aix - Comments: - none -=cut -#------------------------------------------------------------------------------- -sub get_subnet_aix -{ - my @netstat_res = `/usr/bin/netstat -rn`; - chomp @netstat_res; - my @aix_nrn; - for my $entry ( @netstat_res) - { -#We need to find entries like: -#Destination Gateway Flags Refs Use If Exp Groups -#9.114.47.192/27 9.114.47.205 U 1 1 en0 -#4000::/64 link#4 UCX 1 0 en2 - - - my ( $net, $netmask, $flag, $nic); - if ( $entry =~ /^\s*([\d\.]+)\/(\d+)\s+[\d\.]+\s+(\w+)\s+\d+\s+\d+\s(\w+)/) - { - ( $net, $netmask, $flag, $nic) = ($1,$2,$3,$4); - my @dotsec = split /\./, $net; - for ( my $i = 4; $i > scalar(@dotsec); $i--) - { - $net .= '.0'; - } - push @aix_nrn, "$net:$nic:$netmask:$flag" if ($net ne '127.0.0.0'); - } - elsif ($entry =~ /^\s*([\dA-Fa-f\:]+)\/(\d+)\s+.*?\s+(\w+)\s+\d+\s+\d+\s(\w+)/) - { - #print "=====$entry====\n"; - ( $net, $netmask, $flag, $nic) = ($1,$2,$3,$4); - # for ipv6, can not use : as the delimiter - push @aix_nrn, "$net-$nic-$netmask-$flag" if ($net ne '::') - } - } - return @aix_nrn; -} - -#------------------------------------------------------------------------------- - -=head3 isIpaddr - - returns 1 if parameter is has a valid IP address form. - - Arguments: - dot qulaified IP address: e.g. 1.2.3.4 - Returns: - 1 - if legal IP address - 0 - if not legal IP address. - Globals: - none - Error: - none - Example: - if ($ipAddr) { blah; } - Comments: - Doesn't test if the IP address is on the network, - just tests its form. - -=cut - -#------------------------------------------------------------------------------- -sub isIpaddr -{ - my $addr = shift; - if (($addr) && ($addr =~ /xCAT::Utils/)) - { - $addr = shift; - } - - unless ( $addr ) - { - return 0; - } - #print "addr=$addr\n"; - if ($addr !~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/) - { - return 0; - } - - if ($1 > 255 || $1 == 0 || $2 > 255 || $3 > 255 || $4 > 255) - { - return 0; - } - else - { - return 1; - } -} - -#------------------------------------------------------------------------------- - -=head3 getNodeNetworkCfg - Description: - Get node network configuration, including "IP, hostname(the nodename),and netmask" by this node's name. - - Arguments: - node: the nodename - Returns: - Return an array, which contains (IP,hostname,gateway,netmask'). - undef - Failed to get the network configuration info - Globals: - none - Error: - none - Example: - my ($ip,$host,undef,$mask) = xCAT::Utils::getNodeNetworkCfg('node1'); - Comments: - Presently gateway is always blank. Need to be improved. - -=cut - -#------------------------------------------------------------------------------- -sub getNodeNetworkCfg -{ - my $node = shift; - - my $nets = xCAT::Utils::my_nets(); - my $ip = xCAT::NetworkUtils->getipaddr($node); - my $mask = undef; - for my $net (keys %$nets) - { - my $netname; - ($netname,$mask) = split /\//, $net; - last if ( xCAT::Utils::isInSameSubnet( $netname, $ip, $mask, 1)); - } - return ($ip, $node, undef, xCAT::Utils::formatNetmask($mask,1,0)); -} #------------------------------------------------------------------------------- @@ -5781,54 +2499,6 @@ sub get_unique_members #------------------------------------------------------------------------------- -=head3 get_hdwr_ip - Description: - Get hardware(CEC, BPA) IP from the hosts table, and then /etc/hosts. - - Arguments: - node: the nodename(cec, or bpa) - Returns: - Return the node IP - -1 - Failed to get the IP. - Globals: - none - Error: - none - Example: - my $ip = xCAT::Utils::get_hdwr_ip('node1'); - Comments: - Used in FSPpower FSPflash, FSPinv. - -=cut - -#------------------------------------------------------------------------------- -sub get_hdwr_ip -{ - require xCAT::Table; - my $node = shift; - my $ip = undef; - my $Rc = undef; - - my $ip_tmp_res = xCAT::Utils::toIP($node); - ($Rc, $ip) = @$ip_tmp_res; - if ( $Rc ) { - my $hosttab = xCAT::Table->new( 'hosts' ); - if ( $hosttab) { - my $node_ip_hash = $hosttab->getNodeAttribs( $node,[qw(ip)]); - $ip = $node_ip_hash->{ip}; - } - - } - - if (!$ip) { - return undef; - } - - return $ip; -} - -#------------------------------------------------------------------------------- - =head3 updateEtcHosts Description: Add nodes and their IP addresses into /etc/hosts. @@ -6146,237 +2816,9 @@ sub setupAIXconserver return $rc; } -#------------------------------------------------------------------------------- - -=head3 setAppStatus - Description: - Set an AppStatus value for a specific application in the nodelist - appstatus attribute for a list of nodes - Arguments: - @nodes - $application - $status - Returns: - Return result of call to setNodesAttribs - Globals: - none - Error: - none - Example: - xCAT::Utils::setAppStatus(\@nodes,$application,$status); - Comments: - -=cut - -#----------------------------------------------------------------------------- - -sub setAppStatus -{ - require xCAT::Table; - - my ($class, $nodes_ref, $application, $status) = @_; - my @nodes = @$nodes_ref; - - #get current local time to set in appstatustime attribute - my ( - $sec, $min, $hour, $mday, $mon, - $year, $wday, $yday, $isdst - ) - = localtime(time); - my $currtime = sprintf("%02d-%02d-%04d %02d:%02d:%02d", - $mon + 1, $mday, $year + 1900, - $hour, $min, $sec); - - my $nltab = xCAT::Table->new('nodelist'); - my $nodeappstat = $nltab->getNodesAttribs(\@nodes,['appstatus']); - - my %new_nodeappstat; - foreach my $node (keys %$nodeappstat) { - if ( $node =~ /^\s*$/ ) { next; } # Skip blank node names - my $new_appstat = ""; - my $changed = 0; - - # Search current appstatus and change if app entry exists - my $cur_appstat = $nodeappstat->{$node}->[0]->{appstatus}; - if ($cur_appstat) { - my @appstatus_entries = split(/,/,$cur_appstat); - foreach my $appstat (@appstatus_entries) { - my ($app, $stat) = split(/=/,$appstat); - if ($app eq $application) { - $new_appstat .= ",$app=$status"; - $changed = 1; - } else { - $new_appstat .= ",$appstat"; - } - } - } - # If no app entry exists, add it - if (!$changed){ - $new_appstat .= ",$application=$status"; - } - $new_appstat =~ s/^,//; - $new_nodeappstat{$node}->{appstatus} = $new_appstat; - $new_nodeappstat{$node}->{appstatustime} = $currtime; - } - - return $nltab->setNodesAttribs(\%new_nodeappstat); - -} -#------------------------------------------------------------------------------- - -=head3 getAppStatus - Description: - Get an AppStatus value for a specific application from the - nodelist appstatus attribute for a list of nodes - Arguments: - @nodes - $application - Returns: - a hashref of nodes set to application status value - Globals: - none - Error: - none - Example: - my $appstatus = $xCAT::Utils::getAppStatus(\@nodes,$application); - my $node1_status = $appstatus->{node1}; - Comments: - -=cut - -#----------------------------------------------------------------------------- - -sub getAppStatus -{ - require xCAT::Table; - - my ($class, $nodes_ref, $application) = @_; - my @nodes = @$nodes_ref; - - my $nltab = xCAT::Table->new('nodelist'); - my $nodeappstat = $nltab->getNodesAttribs(\@nodes,['appstatus']); - - my $ret_nodeappstat; - foreach my $node (keys %$nodeappstat) { - my $cur_appstat = $nodeappstat->{$node}->[0]->{appstatus}; - my $found = 0; - if ($cur_appstat) { - my @appstatus_entries = split(/,/,$cur_appstat); - foreach my $appstat (@appstatus_entries) { - my ($app, $stat) = split(/=/,$appstat); - if ($app eq $application) { - $ret_nodeappstat->{$node} = $stat; - $found = 1; - } - } - } - # If no app entry exists, return empty - if (!$found){ - $ret_nodeappstat->{$node} = ""; - } - } - - return $ret_nodeappstat; - -} -#------------------------------------------------------------------------------- - -=head3 enableSSH - Description: - Reads the site.sshbetweennodes attribute and determines - if the input node should be enabled to ssh between nodes - Arguments: - $node - Returns: - 1 = enable ssh - 0 = do not enable ssh - Globals: - none - Error: - none - Example: - my $eable = $xCAT::Utils::enablessh($node); - Comments: - -=cut - -#----------------------------------------------------------------------------- - -sub enablessh -{ - - require xCAT::Table; - my ($class, $node) = @_; - my $enablessh=1; - if (xCAT::Utils->isSN($node)) - { - $enablessh=1; # service nodes always enabled - } - else - { - - # if not a service node we need to check, before enabling - my $values; - #if (keys %::XCATSITEVALS) { - # $values=$::XCATSITEVALS{sshbetweennodes}; - #} else { - # my $sitetab = xCAT::Table->new('site'); - # my $attr = "sshbetweennodes"; - # my $ref = $sitetab->getAttribs({key => $attr}, 'value'); - # if ($ref) { - # $values = $ref->{value}; - # } - #} - my @vals = xCAT::Utils->get_site_attribute("sshbetweennodes"); - $values = $vals[0]; - if ($values) { - my @groups = split(/,/, $values); - if (grep(/^ALLGROUPS$/, @groups)) - { - $enablessh=1; - } - else - { - if (grep(/^NOGROUPS$/, @groups)) - { - $enablessh=0; - } - else - { # check to see if the node is a member of a group - my $ismember = 0; - foreach my $group (@groups) - { - $ismember = xCAT::Utils->isMemberofGroup($node, $group); - if ($ismember == 1) - { - last; - } - } - if ($ismember == 1) - { - $enablessh=1; - } - else - { - $enablessh=0; - } - } - } - } - else - { # does not exist, set default - $enablessh=1; - - } - } - - return $enablessh; - -} - #------------------------------------------------------------------------------- =head3 isSELINUX