-Have discovery refuse to give the same IP address to multiple nics by default
-Have nbroot explicitly try to send packets out of each up interface -Prevent empty /etc/motd warnings -Fix issue where discovery failed with classic MM -Change check for network sameness to a live check instead of table check in nodediscover -Have nbroot quiet by default to alleviate conserver log usage -Have dhcp plugin mac deletion be a bit more aggressive, delete matching mac addresses -Have discovery disable DHCP offers for multiple NICs on the same network if nothing resembling a proper guess can be made git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@866 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd
This commit is contained in:
		@@ -1143,6 +1143,41 @@ sub my_hexnets
 | 
			
		||||
    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 {
 | 
			
		||||
   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    
 | 
			
		||||
 
 | 
			
		||||
@@ -80,6 +80,19 @@ while :; do
 | 
			
		||||
        for dhcps in `cat /tmp/dhcpserver`; do 
 | 
			
		||||
         cat /tmp/discout | udpcat.awk $dhcps $XCATPORT &
 | 
			
		||||
        done
 | 
			
		||||
        for nic in `ifconfig -a|grep HWaddr|grep -v sit|awk '{print $1}'`; do #also, bring down interfaces to make sure that we send from the 'right' nic
 | 
			
		||||
         for dnic in `ifconfig -a|grep HWaddr|grep -v sit|awk '{print $1}'|grep -v $nic`; do
 | 
			
		||||
            ifconfig $dnic down
 | 
			
		||||
         done
 | 
			
		||||
         cat /tmp/discout | udpcat.awk $XCATMASTER $XCATPORT & #can't figure out how to make a hung gawk behave..
 | 
			
		||||
         for dhcps in `cat /tmp/dhcpserver`; do 
 | 
			
		||||
            cat /tmp/discout | udpcat.awk $dhcps $XCATPORT &
 | 
			
		||||
         done
 | 
			
		||||
         for dnic in `ifconfig -a|grep HWaddr|grep -v sit|awk '{print $1}'|grep -v $nic`; do
 | 
			
		||||
            ifconfig $dnic up
 | 
			
		||||
         done
 | 
			
		||||
        done
 | 
			
		||||
         
 | 
			
		||||
        usleep 8000000
 | 
			
		||||
      fi
 | 
			
		||||
      killall udpcat.awk #reap hung ones
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,7 @@ hba=0
 | 
			
		||||
 | 
			
		||||
MOD=""
 | 
			
		||||
NICSTOWAIT=""
 | 
			
		||||
touch /etc/motd
 | 
			
		||||
echo "cat /etc/motd" >> /etc/profile
 | 
			
		||||
 | 
			
		||||
#Load common usb drivers
 | 
			
		||||
 
 | 
			
		||||
@@ -171,6 +171,7 @@ sub fillresps {
 | 
			
		||||
  my $response = shift;
 | 
			
		||||
  my $mac = $response->{node}->[0]->{data}->[0]->{contents}->[0];
 | 
			
		||||
  my $node = $response->{node}->[0]->{name}->[0];
 | 
			
		||||
  $mac = uc($mac); #Make sure it is uppercase, the MM people seem to change their mind on this..
 | 
			
		||||
  $macmap{$mac} = $node;
 | 
			
		||||
  #$macmap{$response->{node}->[0]->{data}->{contents}->[0]}=$response->{node}->[0]->{name};
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -44,14 +44,25 @@ sub delnode {
 | 
			
		||||
  	print $omshell "open\n";
 | 
			
		||||
  	print $omshell "remove\n";
 | 
			
		||||
  	print $omshell "close\n";
 | 
			
		||||
   if ($mac) {
 | 
			
		||||
  	   print $omshell "new host\n";
 | 
			
		||||
  	   print $omshell "set hardware-address = ".$mac."\n"; #find and destroy mac conflict
 | 
			
		||||
  	   print $omshell "open\n";
 | 
			
		||||
  	   print $omshell "remove\n";
 | 
			
		||||
  	   print $omshell "close\n";
 | 
			
		||||
   }
 | 
			
		||||
  	if ($inetn) {
 | 
			
		||||
  	  my $ip = inet_ntoa(inet_aton($hname));;
 | 
			
		||||
  	  unless ($ip) { return; }
 | 
			
		||||
  	  print $omshell "new host\n";
 | 
			
		||||
  	  print $omshell "set ip-address = $ip\n"; #find and destroy ip conflict
 | 
			
		||||
  	  print $omshell "open\n";
 | 
			
		||||
  	  print $omshell "remove\n";
 | 
			
		||||
  	  print $omshell "close\n";
 | 
			
		||||
  	  my $ip;
 | 
			
		||||
     if (inet_aton($hname)) {
 | 
			
		||||
      $ip = inet_ntoa(inet_aton($hname));;
 | 
			
		||||
     }
 | 
			
		||||
  	  if ($ip) { 
 | 
			
		||||
  	   print $omshell "new host\n";
 | 
			
		||||
  	   print $omshell "set ip-address = $ip\n"; #find and destroy ip conflict
 | 
			
		||||
  	   print $omshell "open\n";
 | 
			
		||||
  	   print $omshell "remove\n";
 | 
			
		||||
  	   print $omshell "close\n";
 | 
			
		||||
     }
 | 
			
		||||
  	}
 | 
			
		||||
  }
 | 
			
		||||
  }
 | 
			
		||||
@@ -117,16 +128,31 @@ sub addnode {
 | 
			
		||||
  foreach $mace (@macs) {
 | 
			
		||||
	my $mac;
 | 
			
		||||
	my $hname;
 | 
			
		||||
   $hname = "";
 | 
			
		||||
	($mac,$hname) = split (/!/,$mace);	
 | 
			
		||||
	unless ($hname) { $hname = $node; } #Default to hostname equal to nodename
 | 
			
		||||
        unless ($mac) { next; } #Skip corrupt format
 | 
			
		||||
  	my $inetn = inet_aton($hname);
 | 
			
		||||
   unless ($mac) { next; } #Skip corrupt format
 | 
			
		||||
   my $inetn;
 | 
			
		||||
   $inetn="";
 | 
			
		||||
   if ($hname eq '*NOIP*')  {
 | 
			
		||||
      $inetn = "DENIED";
 | 
			
		||||
      $hname = $node."-noip".$mac;
 | 
			
		||||
      $hname =~ s/://g;
 | 
			
		||||
   } else {
 | 
			
		||||
  	   $inetn = inet_aton($hname);
 | 
			
		||||
   }
 | 
			
		||||
  	unless ($inetn) {
 | 
			
		||||
    		syslog("local1|err","xCAT DHCP plugin unable to resolve IP for $hname (for $node)");
 | 
			
		||||
    		return;
 | 
			
		||||
  	}
 | 
			
		||||
        my $ip = inet_ntoa(inet_aton($hname));;
 | 
			
		||||
   if ($guess_next_server) {
 | 
			
		||||
        my $ip;
 | 
			
		||||
        $ip="";
 | 
			
		||||
        if ($inetn eq "DENIED") {
 | 
			
		||||
           $ip = "DENIED";
 | 
			
		||||
        } else {
 | 
			
		||||
         $ip = inet_ntoa(inet_aton($hname));;
 | 
			
		||||
        }
 | 
			
		||||
   if ($guess_next_server and $ip ne "DENIED") {
 | 
			
		||||
        my $nxtsrv = xCAT::Utils->my_ip_facing($hname);
 | 
			
		||||
        if ($nxtsrv) {
 | 
			
		||||
           $lstatements = "next-server $nxtsrv;$statements";
 | 
			
		||||
@@ -152,10 +178,14 @@ sub addnode {
 | 
			
		||||
  	print $omshell "set name = \"$hname\"\n";
 | 
			
		||||
  	print $omshell "set hardware-address = ".$mac."\n";
 | 
			
		||||
  	print $omshell "set hardware-type = 1\n";
 | 
			
		||||
  	print $omshell "set ip-address = $ip\n";
 | 
			
		||||
  	if ($lstatements) {
 | 
			
		||||
  	    print $omshell "set statements = \"$lstatements\"\n";
 | 
			
		||||
  	 }
 | 
			
		||||
   if ($ip eq "DENIED") { #Blacklist this mac to preclude confusion, give best shot at things working
 | 
			
		||||
         print $omshell "set statements = \"deny booting;\"\n";
 | 
			
		||||
   } else {
 | 
			
		||||
      print $omshell "set ip-address = $ip\n";
 | 
			
		||||
      if ($lstatements) {
 | 
			
		||||
         print $omshell "set statements = \"$lstatements\"\n";
 | 
			
		||||
      }
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
  	print $omshell "create\n";
 | 
			
		||||
  	print $omshell "close\n";
 | 
			
		||||
 
 | 
			
		||||
@@ -112,7 +112,7 @@ sub process_request {
 | 
			
		||||
         print $cfgfile "DEFAULT xCAT\n";
 | 
			
		||||
         print $cfgfile "  LABEL xCAT\n";
 | 
			
		||||
         print $cfgfile "  KERNEL xcat/nbk.$arch\n";
 | 
			
		||||
         print $cfgfile "  APPEND initrd=xcat/nbfs.$arch.gz xcatd=".$hexnets->{$_}.":$xcatdport $consolecmdline\n";
 | 
			
		||||
         print $cfgfile "  APPEND initrd=xcat/nbfs.$arch.gz quiet xcatd=".$hexnets->{$_}.":$xcatdport $consolecmdline\n";
 | 
			
		||||
         close($cfgfile);
 | 
			
		||||
      } elsif ($arch =~ /ppc/) {
 | 
			
		||||
         open($cfgfile,">","$tftpdir/etc/".lc($_));
 | 
			
		||||
@@ -120,7 +120,7 @@ sub process_request {
 | 
			
		||||
         print $cfgfile "   label=xcat\n";
 | 
			
		||||
         print $cfgfile "   image=xcat/nbk.$arch\n";
 | 
			
		||||
         print $cfgfile "   initrd=xcat/nbfs.$arch.gz\n";
 | 
			
		||||
         print $cfgfile '   append="xcatd='.$hexnets->{$_}.":$xcatdport $consolecmdline\"\n";
 | 
			
		||||
         print $cfgfile '   append="quiet xcatd='.$hexnets->{$_}.":$xcatdport $consolecmdline\"\n";
 | 
			
		||||
         close($cfgfile);
 | 
			
		||||
      }
 | 
			
		||||
   }
 | 
			
		||||
 
 | 
			
		||||
@@ -13,6 +13,7 @@ use POSIX "WNOHANG";
 | 
			
		||||
use Storable qw(freeze thaw);
 | 
			
		||||
use IO::Select;
 | 
			
		||||
use IO::Handle;
 | 
			
		||||
use xCAT::Utils;
 | 
			
		||||
use Sys::Syslog;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -29,7 +30,9 @@ sub gethosttag {
 | 
			
		||||
   my $node = shift;
 | 
			
		||||
   my $netn = shift;
 | 
			
		||||
   my $ifname = shift;
 | 
			
		||||
   my $mgtifname = "";
 | 
			
		||||
   my $usednames = shift;
 | 
			
		||||
   my %netmap = %{xCAT::Utils::my_if_netmap};
 | 
			
		||||
   my $mgtifname = $netmap{$netn};
 | 
			
		||||
   my $secondpass = 0;
 | 
			
		||||
   my $name = "";
 | 
			
		||||
   my $defhost = inet_aton($node);
 | 
			
		||||
@@ -38,45 +41,41 @@ sub gethosttag {
 | 
			
		||||
   my @netents = @{$nettab->getAllEntries()};
 | 
			
		||||
   my $pass;
 | 
			
		||||
   #TODO: mgtifname field will get trounced in hierarchical setup, use a live check to match accurately
 | 
			
		||||
   foreach $pass (1,2) { #two passes to allow for mgtifname matching
 | 
			
		||||
     foreach (@netents) {
 | 
			
		||||
      if ($_->{net} eq $netn or ($mgtifname and $mgtifname eq $_->{mgtifname})) {
 | 
			
		||||
         $mgtifname = $_->{mgtifname}; #This flags the managementethernet for a second pass
 | 
			
		||||
         if ($_->{nodehostname}) {
 | 
			
		||||
	 	my $left;
 | 
			
		||||
		my $right;
 | 
			
		||||
		($left,$right) = split(/\//,$_->{nodehostname},2);
 | 
			
		||||
		$name = $node;
 | 
			
		||||
	 	$name =~ s/$left/$right/;
 | 
			
		||||
		if ($name and inet_aton($name)) { 
 | 
			
		||||
	          if ($netn eq $_->{net}) { return $name; } 
 | 
			
		||||
		  #At this point, it could still be valid if block was entered due to mgtifname
 | 
			
		||||
	   	  my $nnetn = inet_ntoa(pack("N",unpack("N",inet_aton($name)) & unpack("N",inet_aton($_->{mask}))));
 | 
			
		||||
	          if ($nnetn eq $_->{net}) { return $name; }
 | 
			
		||||
		}
 | 
			
		||||
		$name=""; #Still here, this branch failed
 | 
			
		||||
	}
 | 
			
		||||
	$defn = inet_ntoa(pack("N",unpack("N",$defhost) & unpack("N",inet_aton($_->{mask}))));
 | 
			
		||||
	if ($defn eq $_->{net}) { #the default nodename is on this network
 | 
			
		||||
	   return $node;
 | 
			
		||||
	}
 | 
			
		||||
	my $tentativehost = $node . "-".$ifname;
 | 
			
		||||
	my $tnh = inet_aton($tentativehost);
 | 
			
		||||
	if ($tnh) {
 | 
			
		||||
	   my $nnetn = inet_ntoa(pack("N",unpack("N",$tnh) & unpack("N",inet_aton($_->{mask}))));
 | 
			
		||||
	   if ($nnetn eq $_->{net}) {
 | 
			
		||||
	      return $tentativehost;
 | 
			
		||||
	   }
 | 
			
		||||
	}
 | 
			
		||||
   foreach (@netents) {
 | 
			
		||||
      if ($_->{net} eq $netn or ($mgtifname and $mgtifname eq $netmap{$_->{net}})) { #either is the network  or shares physical interface
 | 
			
		||||
         if ($_->{nodehostname}) { #Check for a nodehostname rule in the table
 | 
			
		||||
            my $left;
 | 
			
		||||
            my $right;
 | 
			
		||||
            ($left,$right) = split(/\//,$_->{nodehostname},2);
 | 
			
		||||
            $name = $node;
 | 
			
		||||
            $name =~ s/$left/$right/;
 | 
			
		||||
            if ($name and inet_aton($name)) { 
 | 
			
		||||
               if ($netn eq $_->{net} and not $usednames->{$name}) { return $name; } 
 | 
			
		||||
               #At this point, it could still be valid if block was entered due to mgtifname
 | 
			
		||||
               my $nnetn = inet_ntoa(pack("N",unpack("N",inet_aton($name)) & unpack("N",inet_aton($_->{mask}))));
 | 
			
		||||
               if ($nnetn eq $_->{net} and not $usednames->{$name}) { return $name; }
 | 
			
		||||
            }
 | 
			
		||||
            $name=""; #Still here, this branch failed
 | 
			
		||||
         }
 | 
			
		||||
         $defn="";
 | 
			
		||||
         if ($defhost) {
 | 
			
		||||
            $defn = inet_ntoa(pack("N",unpack("N",$defhost) & unpack("N",inet_aton($_->{mask}))));
 | 
			
		||||
         }
 | 
			
		||||
         if ($defn eq $_->{net} and not $usednames->{$node}) { #the default nodename is on this network
 | 
			
		||||
            return $node;
 | 
			
		||||
         }
 | 
			
		||||
         my $tentativehost = $node . "-".$ifname;
 | 
			
		||||
         my $tnh = inet_aton($tentativehost);
 | 
			
		||||
         if ($tnh) {
 | 
			
		||||
            my $nnetn = inet_ntoa(pack("N",unpack("N",$tnh) & unpack("N",inet_aton($_->{mask}))));
 | 
			
		||||
            if ($nnetn eq $_->{net} and not $usednames->{$tentativehost}) {
 | 
			
		||||
               return $tentativehost;
 | 
			
		||||
            }
 | 
			
		||||
         }
 | 
			
		||||
      }
 | 
			
		||||
     }
 | 
			
		||||
    }
 | 
			
		||||
   }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
	
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
sub handled_commands {
 | 
			
		||||
  return {
 | 
			
		||||
    #discovered => 'chain:ondiscover',
 | 
			
		||||
@@ -108,6 +107,7 @@ sub process_request {
 | 
			
		||||
    my $mactab = xCAT::Table->new("mac",-create=>1);
 | 
			
		||||
    my @ifinfo;
 | 
			
		||||
    my $macstring = "";
 | 
			
		||||
    my %usednames;
 | 
			
		||||
    foreach (@{$request->{mac}}) {
 | 
			
		||||
       @ifinfo = split /\|/;
 | 
			
		||||
       if ($ifinfo[3]) {
 | 
			
		||||
@@ -116,10 +116,13 @@ sub process_request {
 | 
			
		||||
	  	my $ipn = unpack("N",inet_aton($ip));
 | 
			
		||||
		my $mask = 2**$netbits-1<<(32-$netbits);
 | 
			
		||||
		my $netn = inet_ntoa(pack("N",$ipn & $mask));
 | 
			
		||||
		my $hosttag = gethosttag($node,$netn,@ifinfo[1]);
 | 
			
		||||
		my $hosttag = gethosttag($node,$netn,@ifinfo[1],\%usednames);
 | 
			
		||||
		if ($hosttag) {
 | 
			
		||||
         $usednames{$hosttag}=1;
 | 
			
		||||
		   $macstring .= $ifinfo[2]."!".$hosttag."|";
 | 
			
		||||
		}
 | 
			
		||||
		} else {
 | 
			
		||||
         $macstring .= $ifinfo[2]."!*NOIP*|";
 | 
			
		||||
      }
 | 
			
		||||
	  }
 | 
			
		||||
       }
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -115,7 +115,9 @@ sub setstate {
 | 
			
		||||
         my @macs = split(/\|/,$ment->{mac});
 | 
			
		||||
         foreach (@macs) {
 | 
			
		||||
            if (/!(.*)/) {
 | 
			
		||||
               $ipaddrs{inet_ntoa(inet_aton($1))} = 1;
 | 
			
		||||
               if (inet_aton($1)) {
 | 
			
		||||
                  $ipaddrs{inet_ntoa(inet_aton($1))} = 1;
 | 
			
		||||
               }
 | 
			
		||||
            }
 | 
			
		||||
         }
 | 
			
		||||
     }
 | 
			
		||||
 
 | 
			
		||||
@@ -32,6 +32,14 @@ sub process_request {
 | 
			
		||||
   return;
 | 
			
		||||
 }
 | 
			
		||||
 my $node = $macmap->find_mac($mac,$req->{cacheonly}->[0]);
 | 
			
		||||
 #if (not $node and $req->{checkallmacs}->[0]) {
 | 
			
		||||
 #   foreach (@{$req->{mac}}) {
 | 
			
		||||
 #      /.*\|.*\|([\dABCDEFabcdef:]+)(\||$)/;
 | 
			
		||||
 #      $node = $macmap->find_mac($1,$req->{cacheonly}->[0]);
 | 
			
		||||
 #      if ($node) { last; }
 | 
			
		||||
 #   }
 | 
			
		||||
 #}
 | 
			
		||||
    
 | 
			
		||||
 if ($node) {
 | 
			
		||||
  my $mactab = xCAT::Table->new('mac',-create=>1);
 | 
			
		||||
  $mactab->setNodeAttribs($node,{mac=>$mac});
 | 
			
		||||
 
 | 
			
		||||
@@ -121,7 +121,9 @@ sub setstate {
 | 
			
		||||
        my @macs = split(/\|/,$ment->{mac});
 | 
			
		||||
        foreach (@macs) {
 | 
			
		||||
           if (/!(.*)/) {
 | 
			
		||||
              $ipaddrs{inet_ntoa(inet_aton($1))} = 1;
 | 
			
		||||
              if (inet_aton($1)) {
 | 
			
		||||
               $ipaddrs{inet_ntoa(inet_aton($1))} = 1;
 | 
			
		||||
              }
 | 
			
		||||
           }
 | 
			
		||||
        }
 | 
			
		||||
     }
 | 
			
		||||
 
 | 
			
		||||
@@ -279,6 +279,12 @@ if ($inet6support) {
 | 
			
		||||
  	    if ($req->{cacheonly}->[0]) {
 | 
			
		||||
		delete $req->{cacheonly};
 | 
			
		||||
                plugin_command($req,undef,\&convey_response);
 | 
			
		||||
           #if ($req) {
 | 
			
		||||
           #   $req->{cacheonly}->[0] = 1;
 | 
			
		||||
           #   $req->{checkallmacs}->[0] = 1;
 | 
			
		||||
           #     plugin_command($req,undef,\&convey_response);
 | 
			
		||||
           # }
 | 
			
		||||
 | 
			
		||||
	    }
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user