From 06d2048be2c330a2380e8118d1766a61ae73d991 Mon Sep 17 00:00:00 2001
From: nott <nott@8638fb3e-16cb-4fca-ae20-7b5d299a9bcd>
Date: Mon, 3 Dec 2012 20:23:33 +0000
Subject: [PATCH] add domain and nics table support

git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@14529 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd
---
 xCAT-server/lib/xcat/plugins/hosts.pm | 690 +++++++++++++++++---------
 1 file changed, 466 insertions(+), 224 deletions(-)

diff --git a/xCAT-server/lib/xcat/plugins/hosts.pm b/xCAT-server/lib/xcat/plugins/hosts.pm
index 58594e9ab..3042585ed 100644
--- a/xCAT-server/lib/xcat/plugins/hosts.pm
+++ b/xCAT-server/lib/xcat/plugins/hosts.pm
@@ -10,264 +10,506 @@ use File::Copy;
 use Getopt::Long;
 use Fcntl ':flock';
 
-
-my @hosts; #Hold /etc/hosts data to be written back
+my @hosts;    #Hold /etc/hosts data to be written back
 my $LONGNAME;
 my $OTHERNAMESFIRST;
 my $ADDNAMES;
 my $MACTOLINKLOCAL;
 
+my %usage =
+  (makehosts =>
+    "Usage: makehosts <noderange> [-d] [-n] [-l] [-a] [-o] [-m]\n       makehosts -h",
+    );
 
-my %usage=(
-    makehosts => "Usage: makehosts <noderange> [-d] [-n] [-l] [-a] [-o] [-m]\n       makehosts -h",
-);
-sub handled_commands {
-  return {
-    makehosts => "hosts",
-  }
+sub handled_commands
+{
+    return {makehosts => "hosts",};
 }
-  
 
-sub delnode {
-  my $node = shift;
-  my $ip = shift;
-  unless ($node and $ip) { return; } #bail if requested to do something that could zap /etc/hosts badly
-  my $othernames = shift;
-  my $domain = shift;
-  my $idx=0;
-  
-  while ($idx <= $#hosts) {
-    if (($ip and $hosts[$idx] =~ /^${ip}\s/) or $hosts[$idx] =~ /^\d+\.\d+\.\d+\.\d+\s+${node}[\s\.r]/) {
-        $hosts[$idx]=""; 
+sub delnode
+{
+    my $node = shift;
+    my $ip   = shift;
+
+    unless ($node and $ip)
+    {
+        return;
+    }    #bail if requested to do something that could zap /etc/hosts badly
+
+    my $othernames = shift;
+    my $domain     = shift;
+    my $idx        = 0;
+
+    while ($idx <= $#hosts)
+    {
+        if (($ip and $hosts[$idx] =~ /^${ip}\s/)
+            or $hosts[$idx] =~ /^\d+\.\d+\.\d+\.\d+\s+${node}[\s\.r]/)
+        {
+            $hosts[$idx] = "";
+        }
+        $idx++;
     }
-    $idx++;
-  }
 }
 
-sub addnode {
-  my $node = shift;
-  my $ip = shift;
-  unless ($node and $ip) { return; } #bail if requested to do something that could zap /etc/hosts badly
-  my $othernames = shift;
-  my $domain = shift;
-  my $idx=0;
-  my $foundone=0;
-  
-  while ($idx <= $#hosts) {
-    if ($hosts[$idx] =~ /^${ip}\s/ or $hosts[$idx] =~ /^\d+\.\d+\.\d+\.\d+\s+${node}[\s\.r]/) {
-      if ($foundone) {
-        $hosts[$idx]=""; 
-      } else {
-        $hosts[$idx]=build_line($ip, $node, $domain, $othernames); 
-      }
-      $foundone=1;
+sub addnode
+{
+    my $node = shift;
+    my $ip   = shift;
+
+    unless ($node and $ip)
+    {
+        return;
+    }    #bail if requested to do something that could zap /etc/hosts badly
+
+    my $othernames = shift;
+    my $domain     = shift;
+    my $idx        = 0;
+    my $foundone   = 0;
+
+    while ($idx <= $#hosts)
+    {
+        if (   $hosts[$idx] =~ /^${ip}\s/
+            or $hosts[$idx] =~ /^\d+\.\d+\.\d+\.\d+\s+${node}[\s\.r]/)
+        {
+            if ($foundone)
+            {
+                $hosts[$idx] = "";
+            }
+            else
+            {
+                $hosts[$idx] = build_line($ip, $node, $domain, $othernames);
+            }
+            $foundone = 1;
+        }
+        $idx++;
     }
-    $idx++;
-  }
-  if ($foundone) { return;}
+    if ($foundone) { return; }
 
-  my $line=build_line($ip, $node, $domain, $othernames); 
-  push @hosts, $line;
+    my $line = build_line($ip, $node, $domain, $othernames);
+    push @hosts, $line;
 }
 
-sub build_line {
-    my $ip=shift; 
-    my $node=shift;
-    my $domain=shift;
-    my $othernames=shift;
-    my @o_names=();
-    my @n_names=();
-    if (defined $othernames) {
-         @o_names=split(/,| /, $othernames);
+sub build_line
+{
+    my $ip         = shift;
+    my $node       = shift;
+    my $domain     = shift;
+    my $othernames = shift;
+    my @o_names    = ();
+    my @n_names    = ();
+    if (defined $othernames)
+    {
+        @o_names = split(/,| /, $othernames);
     }
     my $longname;
-    foreach (@o_names) {
-	if (($_ eq $node) || ( $domain && ($_ eq "$node.$domain"))) {
-            $longname="$node.$domain";
-	    $_="";
-	} elsif ( $_ =~ /\./) {
-            if (!$longname) { 
-		$longname=$_;
-		$_="";
-	    }
-	} elsif ($ADDNAMES) {
-        unshift(@n_names,"$_.$domain");
-    } 
+    foreach (@o_names)
+    {
+        if (($_ eq $node) || ($domain && ($_ eq "$node.$domain")))
+        {
+            $longname = "$node.$domain";
+            $_        = "";
+        }
+        elsif ($_ =~ /\./)
+        {
+            if (!$longname)
+            {
+                $longname = $_;
+                $_        = "";
+            }
+        }
+        elsif ($ADDNAMES)
+        {
+            unshift(@n_names, "$_.$domain");
+        }
     }
-    unshift(@o_names,@n_names);
+    unshift(@o_names, @n_names);
 
-    if ($node =~ m/\.$domain$/i) {
+    if ($node =~ m/\.$domain$/i)
+    {
         $longname = $node;
         $node =~ s/\.$domain$//;
-    } elsif ($domain && !$longname) {
-	    $longname="$node.$domain";
-    } 
+    }
+    elsif ($domain && !$longname)
+    {
+        $longname = "$node.$domain";
+    }
 
-    $othernames=join(' ', @o_names);
-    if ($LONGNAME) { return "$ip $longname $node $othernames\n"; } 
+    $othernames = join(' ', @o_names);
+    if    ($LONGNAME)        { return "$ip $longname $node $othernames\n"; }
     elsif ($OTHERNAMESFIRST) { return "$ip $othernames $longname $node\n"; }
     else { return "$ip $node $longname $othernames\n"; }
 }
 
+sub addotherinterfaces
+{
+    my $node            = shift;
+    my $otherinterfaces = shift;
+    my $domain          = shift;
 
-sub addotherinterfaces {
-  my $node = shift;
-  my $otherinterfaces = shift;
-  my $domain = shift;
-
-    my @itf_pairs=split(/,/, $otherinterfaces);
-    foreach (@itf_pairs) {
-      my ($itf,$ip)=split(/:/, $_);
-      if ( $ip && xCAT::NetworkUtils->isIpaddr($ip) ) {
-          if ($itf =~ /^-/ ) {
-              $itf = $node.$itf };
-          addnode $itf,$ip,'',$domain;
-      }
-    }
-}
-
-
-sub process_request {
-  Getopt::Long::Configure("bundling") ;
-  $Getopt::Long::ignorecase=0;
-  Getopt::Long::Configure("no_pass_through");
-
-  my $req = shift;
-  my $callback = shift;
-  my $HELP;
-  my $REMOVE;
-  my $DELNODE;
-
-  # parse the options
-  if ($req && $req->{arg}) {@ARGV = @{$req->{arg}};}
-  else {  @ARGV = (); }
-
-# print "argv=@ARGV\n";
-  if(!GetOptions(
-      'h|help'  => \$HELP,
-      'n'  => \$REMOVE,
-      'd'  => \$DELNODE,
-      'o|othernamesfirst'  => \$OTHERNAMESFIRST,
-      'a|adddomaintohostnames'  => \$ADDNAMES,
-      'm|mactolinklocal'  => \$MACTOLINKLOCAL,
-      'l|longnamefirst'  => \$LONGNAME,))
-  {
-    $callback->({data=>$usage{makehosts}});
-    return;
-  }
-
-  # display the usage if -h
-  if ($HELP) { 
-    $callback->({data=>$usage{makehosts}});
-    return;
-  }
-
-
-  my $hoststab = xCAT::Table->new('hosts');
-  #my $sitetab = xCAT::Table->new('site');
-  my $domain;
-  my $lockh;
-  #if ($sitetab) {
-    #my $dent = $sitetab->getAttribs({key=>'domain'},'value');
-    my @entries =  xCAT::TableUtils->get_site_attribute("domain");
-    my $t_entry = $entries[0];
-    if ( defined($t_entry) ) {
-        $domain=$t_entry;
-    }
-  #}
-
-  @hosts = ();
-  if ($REMOVE) {
-    if (-e "/etc/hosts") {
-      my $bakname = "/etc/hosts.xcatbak";
-      rename("/etc/hosts",$bakname);
-      
-      # add the localhost entry if trying to create the /etc/hosts from scratch
-      if ($^O =~ /^aix/i) {
-        push @hosts, "127.0.0.1 loopback localhost\n";
-      } else {
-        push @hosts, "127.0.0.1 localhost\n";
-      }
-    }
-  } else {
-    if (-e "/etc/hosts") {
-      my $bakname = "/etc/hosts.xcatbak";
-      copy("/etc/hosts",$bakname);
-    }
-    open($lockh,">","/tmp/xcat/hostsfile.lock");
-    flock($lockh,LOCK_EX);
-    my $rconf;
-    open($rconf,"/etc/hosts"); # Read file into memory
-    if ($rconf) {
-      while (<$rconf>) {
-        push @hosts,$_;
-      }
-      close($rconf);
-    }
-  }
-
-  if ($req->{node}) {
-    if ($MACTOLINKLOCAL) {
-        my $mactab = xCAT::Table->new("mac");
-        my $machash = $mactab->getNodesAttribs($req->{node},['mac']);
-        foreach my $node (keys %{$machash})
+    my @itf_pairs = split(/,/, $otherinterfaces);
+    foreach (@itf_pairs)
+    {
+        my ($itf, $ip) = split(/:/, $_);
+        if ($ip && xCAT::NetworkUtils->isIpaddr($ip))
         {
-            my $mac = $machash->{$node}->[0]->{mac};
-            if (!$mac) {
-                next;
+            if ($itf =~ /^-/)
+            {
+                $itf = $node . $itf;
             }
-            my $linklocal = xCAT::NetworkUtils->linklocaladdr($mac);
-            if ($DELNODE) {
-              delnode $node,$linklocal,$node,$domain;
-            } else {
-              addnode $node,$linklocal,$node,$domain;
-            }
-        }
-    } else {
-        my $hostscache = $hoststab->getNodesAttribs($req->{node},[qw(ip node hostnames otherinterfaces)]);
-        foreach(@{$req->{node}}) {
-          my $ref = $hostscache->{$_}->[0]; #$hoststab->getNodeAttribs($_,[qw(ip node hostnames otherinterfaces)]);
-          if ($DELNODE) {
-              delnode $ref->{node},$ref->{ip},$ref->{hostnames},$domain;
-          } else {
-              if ( xCAT::NetworkUtils->isIpaddr($ref->{ip}) ) { 
-                  addnode $ref->{node},$ref->{ip},$ref->{hostnames},$domain;
-              }
-              if (defined($ref->{otherinterfaces})){
-                  addotherinterfaces $ref->{node},$ref->{otherinterfaces},$domain;
-              }
-          }
-        } #end foreach
-    } # end else
-  } else {
-      if ($DELNODE) {
-          return;
-      }
-    my @hostents = $hoststab->getAllNodeAttribs(['ip','node','hostnames','otherinterfaces']);
-    foreach (@hostents) {
-        if ( xCAT::NetworkUtils->isIpaddr($_->{ip}) ) {
-            addnode $_->{node},$_->{ip},$_->{hostnames},$domain;
-        }
-        if (defined($_->{otherinterfaces})){
-           addotherinterfaces $_->{node},$_->{otherinterfaces},$domain;
+            addnode $itf, $ip, '', $domain;
         }
     }
-  }
-  writeout();
-  
-  if ($lockh) {
-    flock($lockh,LOCK_UN);
-  }
 }
 
+sub process_request
+{
+    Getopt::Long::Configure("bundling");
+    $Getopt::Long::ignorecase = 0;
+    Getopt::Long::Configure("no_pass_through");
 
-sub writeout {
-  my $targ;
-  open($targ,'>',"/etc/hosts");
-  foreach (@hosts) {
-    print $targ $_;
-  }
-  close($targ)
+    my $req      = shift;
+    my $callback = shift;
+    my $HELP;
+    my $REMOVE;
+
+    # parse the options
+    if ($req && $req->{arg}) { @ARGV = @{$req->{arg}}; }
+    else { @ARGV = (); }
+
+    # print "argv=@ARGV\n";
+    if (
+        !GetOptions(
+                    'h|help'                 => \$HELP,
+                    'n'                      => \$REMOVE,
+                    'd'                      => \$::DELNODE,
+                    'o|othernamesfirst'      => \$OTHERNAMESFIRST,
+                    'a|adddomaintohostnames' => \$ADDNAMES,
+                    'm|mactolinklocal'       => \$MACTOLINKLOCAL,
+                    'l|longnamefirst'        => \$LONGNAME,
+        )
+      )
+    {
+        $callback->({data => $usage{makehosts}});
+        return;
+    }
+
+    # display the usage if -h
+    if ($HELP)
+    {
+        $callback->({data => $usage{makehosts}});
+        return;
+    }
+
+    my $hoststab = xCAT::Table->new('hosts');
+    my $domain;
+    my $lockh;
+
+    @hosts = ();
+    if ($REMOVE)
+    {
+        if (-e "/etc/hosts")
+        {
+            my $bakname = "/etc/hosts.xcatbak";
+            rename("/etc/hosts", $bakname);
+
+            # add the localhost entry if trying to create the /etc/hosts from scratch
+            if ($^O =~ /^aix/i)
+            {
+                push @hosts, "127.0.0.1 loopback localhost\n";
+            }
+            else
+            {
+                push @hosts, "127.0.0.1 localhost\n";
+            }
+        }
+    }
+    else
+    {
+        if (-e "/etc/hosts")
+        {
+            my $bakname = "/etc/hosts.xcatbak";
+            copy("/etc/hosts", $bakname);
+        }
+        open($lockh, ">", "/tmp/xcat/hostsfile.lock");
+        flock($lockh, LOCK_EX);
+        my $rconf;
+        open($rconf, "/etc/hosts");    # Read file into memory
+        if ($rconf)
+        {
+            while (<$rconf>)
+            {
+                push @hosts, $_;
+            }
+            close($rconf);
+        }
+    }
+
+    if ($req->{node})
+    {
+        if ($MACTOLINKLOCAL)
+        {
+            my $mactab = xCAT::Table->new("mac");
+            my $machash = $mactab->getNodesAttribs($req->{node}, ['mac']);
+            foreach my $node (keys %{$machash})
+            {
+
+                my $mac = $machash->{$node}->[0]->{mac};
+                if (!$mac)
+                {
+                    next;
+                }
+                my $linklocal = xCAT::NetworkUtils->linklocaladdr($mac);
+
+                $domain = &getIPdomain($linklocal, $callback);
+
+                if ($::DELNODE)
+                {
+                    delnode $node, $linklocal, $node, $domain;
+                }
+                else
+                {
+                    addnode $node, $linklocal, $node, $domain;
+                }
+            }
+        }
+        else
+        {
+            my $hostscache =
+              $hoststab->getNodesAttribs($req->{node},
+                                       [qw(ip node hostnames otherinterfaces)]);
+            foreach (@{$req->{node}})
+            {
+
+                my $ref = $hostscache->{$_}->[0];
+                $domain = &getIPdomain($ref->{ip}, $callback);
+
+                if ($::DELNODE)
+                {
+                    delnode $ref->{node}, $ref->{ip}, $ref->{hostnames}, $domain;
+                }
+                else
+                {
+                    if (xCAT::NetworkUtils->isIpaddr($ref->{ip}))
+                    {
+                        addnode $ref->{node}, $ref->{ip}, $ref->{hostnames}, $domain;
+                    }
+                    if (defined($ref->{otherinterfaces}))
+                    {
+                        addotherinterfaces $ref->{node}, $ref->{otherinterfaces}, $domain;
+                    }
+                }
+            }    #end foreach
+        }    # end else
+
+        # do the other node nics - if any
+        &donics($req->{node}, $callback);
+
+    }
+    else
+    {
+        if ($::DELNODE)
+        {
+            return;
+        }
+        my @hostents =
+          $hoststab->getAllNodeAttribs(
+                                ['ip', 'node', 'hostnames', 'otherinterfaces']);
+
+        my @allnodes;
+        foreach (@hostents)
+        {
+
+            push @allnodes, $_->{node};
+
+            $domain = &getIPdomain($_->{ip});
+
+            if (xCAT::NetworkUtils->isIpaddr($_->{ip}))
+            {
+                addnode $_->{node}, $_->{ip}, $_->{hostnames}, $domain;
+            }
+            if (defined($_->{otherinterfaces}))
+            {
+                addotherinterfaces $_->{node}, $_->{otherinterfaces}, $domain;
+            }
+        }
+
+        # also do nics table
+        &donics(\@allnodes, $callback);
+    }
+
+    writeout();
+
+    if ($lockh)
+    {
+        flock($lockh, LOCK_UN);
+    }
+}
+
+sub writeout
+{
+    my $targ;
+    open($targ, '>', "/etc/hosts");
+    foreach (@hosts)
+    {
+        print $targ $_;
+    }
+    close($targ);
+}
+
+#-------------------------------------------------------------------------------
+
+=head3    donics
+
+           Add the additional network interfaces for a list of nodes as 
+				indicated in the nics table
+
+        Arguments:
+               node name
+        Returns:
+			0 - ok
+			1 - error
+
+        Globals:
+
+        Example:
+                my $rc = &donics($node, $callback);
+
+        Comments:
+                none
+=cut
+
+#-------------------------------------------------------------------------------
+sub donics
+{
+    my $nodes    = shift;
+    my $callback = shift;
+
+    my @nodelist = @{$nodes};
+
+    my $nicstab = xCAT::Table->new('nics');
+    my $nettab  = xCAT::Table->new('networks');
+
+    foreach my $node (@nodelist)
+    {
+        my %nichash;
+
+        # get the nic info
+        my $et =
+          $nicstab->getNodeAttribs(
+                                   $node,
+                                   [
+                                    'nicips', 'nichostnamesuffixes',
+                                    'nicnetworks'
+                                   ]
+                                   );
+
+        if (
+            !(
+                  $et->{nicips}
+               && $et->{'nichostnamesuffixes'}
+               && $et->{'nicnetworks'}
+            )
+          )
+        {
+            next;
+        }
+
+        #  $et->{nicips} looks like "eth0:ip1,eth1:ip2,bmc:ip3..."
+        my @nicandiplist = split(',', $et->{'nicips'});
+        foreach (@nicandiplist)
+        {
+            my ($nicname, $nicip) = split(':', $_);
+            $nichash{$nicname}{nicip} = $nicip;
+        }
+        my @nicandsufx = split(',', $et->{'nichostnamesuffixes'});
+        foreach (@nicandsufx)
+        {
+            my ($nicname, $nicsufx) = split(':', $_);
+            $nichash{$nicname}{nicsufx} = $nicsufx;
+        }
+        my @nicandnetwrk = split(',', $et->{'nicnetworks'});
+        foreach (@nicandnetwrk)
+        {
+            my ($nicname, $netwrk) = split(':', $_);
+            $nichash{$nicname}{netwrk} = $netwrk;
+        }
+
+        foreach my $nic (keys %nichash)
+        {
+            # make sure we have the short hostname
+            my $shorthost;
+            ($shorthost = $node) =~ s/\..*$//;
+
+            # construct hostname for nic
+            my $nichostname = "$shorthost$nichash{$nic}{nicsufx}";
+
+            # get domain from network def
+			my $nt = $nettab->getAttribs({ netname => "$nichash{$nic}{netwrk}"}, 'domain');
+
+            if ($::DELNODE)
+            {
+                delnode $nichostname, $nichash{$nic}{nicip}, '', $nt->{domain};
+            }
+            else
+            {
+                addnode $nichostname, $nichash{$nic}{nicip}, '', $nt->{domain};
+            }
+        }    # end for each nic
+    }    # end for each node
+
+    $nettab->close;
+    $nicstab->close;
+
+    return 0;
+}
+
+#-------------------------------------------------------------------------------
+
+=head3    getIPdomain
+
+			Find the xCAT network definition match the IP and then return the
+				domain value from that network def.
+
+        Arguments:
+               node IP
+				callback
+        Returns:
+            domain name - ok
+            1 - error
+
+        Globals:
+
+        Example:
+                my $rc = &getIPdomain($nodeIP, $callback);
+
+        Comments:
+                none
+=cut
+
+#-------------------------------------------------------------------------------
+sub getIPdomain
+{
+    my $nodeIP   = shift;
+    my $callback = shift;
+
+    # get the network defs
+    my $nettab = xCAT::Table->new('networks');
+    my @nets   = $nettab->getAllAttribs('netname', 'net', 'mask', 'domain');
+
+    # foreach network def
+    foreach my $enet (@nets)
+    {
+        my $NM  = $enet->{'mask'};
+        my $net = $enet->{'net'};
+        if (xCAT::NetworkUtils->ishostinsubnet($nodeIP, $NM, $net))
+        {
+            return $enet->{'domain'};
+            last;
+        }
+    }
+
+    # could not find the network domain for this IP address
+    return 1;
 }
 
 1;