mirror of
				https://github.com/xcat2/xcat-core.git
				synced 2025-11-04 05:12:30 +00:00 
			
		
		
		
	Multi-interface discovery support
git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@261 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd
This commit is contained in:
		@@ -67,7 +67,7 @@ package xCAT::Schema;
 | 
			
		||||
    keys => [qw(node)],
 | 
			
		||||
  },
 | 
			
		||||
  networks => {
 | 
			
		||||
    cols => [qw(netname net mask gateway dhcpserver tftpserver nameservers dynamicrange comments disable)],
 | 
			
		||||
    cols => [qw(netname net mask mgtifname gateway dhcpserver tftpserver nameservers dynamicrange nodehostname comments disable)],
 | 
			
		||||
    keys => [qw(net mask)]
 | 
			
		||||
  },
 | 
			
		||||
  osimage  => {
 | 
			
		||||
 
 | 
			
		||||
@@ -55,7 +55,8 @@ while :; do
 | 
			
		||||
      for i in `ifconfig -a|grep HWaddr|grep -v sit|awk '{print $1 "|" $5}'`; do 
 | 
			
		||||
        IFACE=`echo $i|awk -F'|' '{print $1}'`
 | 
			
		||||
        DRIVER=`ethtool -i $IFACE|grep ^driver|awk '{print $2}'`
 | 
			
		||||
        echo "<mac>$DRIVER|$i</mac>"
 | 
			
		||||
        ADDRESS=`ip address show dev $IFACE|grep 'inet '|awk '{print $2}'`
 | 
			
		||||
        echo "<mac>$DRIVER|$i|$ADDRESS</mac>"
 | 
			
		||||
      done
 | 
			
		||||
      modprobe ipmi_devintf
 | 
			
		||||
      if modprobe ipmi_si; then
 | 
			
		||||
 
 | 
			
		||||
@@ -57,45 +57,54 @@ sub addnode {
 | 
			
		||||
  my $ent;
 | 
			
		||||
  my $mactab = xCAT::Table->new('mac');
 | 
			
		||||
  unless ($mactab) { return; } #TODO: report error sanely
 | 
			
		||||
  $ent = $mactab->getNodeAttribs($node,[qw(mac interface)]);
 | 
			
		||||
  $ent = $mactab->getNodeAttribs($node,[qw(mac)]);
 | 
			
		||||
  unless ($ent and $ent->{mac}) {
 | 
			
		||||
    return; #TODO: sane error
 | 
			
		||||
  }
 | 
			
		||||
  my $inetn = inet_aton($node);
 | 
			
		||||
  unless ($inetn) {
 | 
			
		||||
    syslog("local1|err","xCAT DHCP plugin unable to resolve IP for $node");
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  my $ip = inet_ntoa(inet_aton($node));;
 | 
			
		||||
  print "Setting $node ($ip) to ".$ent->{mac}."\n";
 | 
			
		||||
  print $omshell "new host\n";
 | 
			
		||||
  print $omshell "set name = \"$node\"\n"; #Find and destroy conflict name
 | 
			
		||||
  print $omshell "open\n";
 | 
			
		||||
  print $omshell "remove\n";
 | 
			
		||||
  print $omshell "close\n";
 | 
			
		||||
  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";
 | 
			
		||||
  print $omshell "new host\n";
 | 
			
		||||
  print $omshell "set hardware-address = ".$ent->{mac}."\n"; #find and destroy mac conflict
 | 
			
		||||
  print $omshell "open\n";
 | 
			
		||||
  print $omshell "remove\n";
 | 
			
		||||
  print $omshell "close\n";
 | 
			
		||||
  print $omshell "new host\n";
 | 
			
		||||
  print $omshell "set name = \"$node\"\n";
 | 
			
		||||
  print $omshell "set hardware-address = ".$ent->{mac}."\n";
 | 
			
		||||
  print $omshell "set hardware-type = 1\n";
 | 
			
		||||
  print $omshell "set ip-address = $ip\n";
 | 
			
		||||
  if ($statements) {
 | 
			
		||||
      print $omshell "set statements = \"$statements\"\n";
 | 
			
		||||
  my @macs = split(/\|/,$ent->{mac});
 | 
			
		||||
  my $mace;
 | 
			
		||||
  foreach $mace (@macs) {
 | 
			
		||||
	my $mac;
 | 
			
		||||
	my $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 ($inetn) {
 | 
			
		||||
    		syslog("local1|err","xCAT DHCP plugin unable to resolve IP for $hname (for $node)");
 | 
			
		||||
    		return;
 | 
			
		||||
  	}
 | 
			
		||||
        my $ip = inet_ntoa(inet_aton($hname));;
 | 
			
		||||
  	print "Setting $node ($hname|$ip) to ".$ent->{mac}."\n";
 | 
			
		||||
  	print $omshell "new host\n";
 | 
			
		||||
  	print $omshell "set name = \"$hname\"\n"; #Find and destroy conflict name
 | 
			
		||||
  	print $omshell "open\n";
 | 
			
		||||
  	print $omshell "remove\n";
 | 
			
		||||
  	print $omshell "close\n";
 | 
			
		||||
  	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";
 | 
			
		||||
  	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";
 | 
			
		||||
  	print $omshell "new host\n";
 | 
			
		||||
  	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 ($statements) {
 | 
			
		||||
  	    print $omshell "set statements = \"$statements\"\n";
 | 
			
		||||
  	 }
 | 
			
		||||
  	print $omshell "create\n";
 | 
			
		||||
  	unless (grep /#definition for host $node aka host $hname/,@dhcpconf) {
 | 
			
		||||
  	  push @dhcpconf,"#definition for host $node aka host $hname can be found in the dhcpd.leases file\n";
 | 
			
		||||
  	}
 | 
			
		||||
   }
 | 
			
		||||
  print $omshell "create\n";
 | 
			
		||||
  unless (grep /#definition for host $node/,@dhcpconf) {
 | 
			
		||||
    push @dhcpconf,"#definition for host $node can be found in the dhcpd.leases file\n";
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
}	
 | 
			
		||||
sub process_request {
 | 
			
		||||
  my $req = shift;
 | 
			
		||||
  $callback = shift;
 | 
			
		||||
 
 | 
			
		||||
@@ -35,12 +35,14 @@ sub process_request {
 | 
			
		||||
  foreach (@rtable) { #should be the lines to think about, do something with U, and something else with UG
 | 
			
		||||
    my $net;
 | 
			
		||||
    my $mask;
 | 
			
		||||
    my $mgtifname;
 | 
			
		||||
    my $gw;
 | 
			
		||||
    my @ent = split /\s+/,$_;
 | 
			
		||||
    if ($ent[3] eq 'U') {
 | 
			
		||||
      $net = $ent[0];
 | 
			
		||||
      $mask = $ent[2];
 | 
			
		||||
      $nettab->setAttribs({'net'=>$net},{'mask'=>$mask});
 | 
			
		||||
      $mgtifname = $ent[7];
 | 
			
		||||
      $nettab->setAttribs({'net'=>$net},{'mask'=>$mask,'mgtifname'=>$mgtifname});
 | 
			
		||||
      my $tent = $nettab->getAttribs({'net'=>$net},nameservers);
 | 
			
		||||
      unless ($tent and $tent->{nameservers}) {
 | 
			
		||||
        my $text = join ',',@nameservers;
 | 
			
		||||
 
 | 
			
		||||
@@ -16,6 +16,66 @@ use IO::Handle;
 | 
			
		||||
use Sys::Syslog;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
sub gethosttag {
 | 
			
		||||
   #This function tries to return a good hostname for a node based on the
 | 
			
		||||
   #network to which it is connected (by $netn or maybe $ifname)
 | 
			
		||||
   #heuristic:
 | 
			
		||||
   #if the client had a valid IP address from a dhcp server, that is used as key
 | 
			
		||||
   #once the matching network is found, and an explicit mapping defined, try that
 | 
			
		||||
   #next, try to see if the ip for the case where hostname==nodename is on this net, if so, return that
 | 
			
		||||
   #next, try to do nodename-ifname, return that if successful
 | 
			
		||||
   #next, repeat process for all networks that have the common mgtifname field
 | 
			
		||||
   #return undef for now if none of the above worked
 | 
			
		||||
   my $node = shift;
 | 
			
		||||
   my $netn = shift;
 | 
			
		||||
   my $ifname = shift;
 | 
			
		||||
   my $mgtifname = "";
 | 
			
		||||
   my $secondpass = 0;
 | 
			
		||||
   my $name = "";
 | 
			
		||||
   my $defhost = inet_aton($node);
 | 
			
		||||
   my $nettab = xCAT::Table->new('networks');
 | 
			
		||||
   my $defn="";
 | 
			
		||||
   my @netents = @{$nettab->getAllEntries()};
 | 
			
		||||
   my $pass;
 | 
			
		||||
   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;
 | 
			
		||||
	   }
 | 
			
		||||
	}
 | 
			
		||||
      }
 | 
			
		||||
     }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
	
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
sub handled_commands {
 | 
			
		||||
  return {
 | 
			
		||||
    discovered => 'chain:ondiscover',
 | 
			
		||||
@@ -41,6 +101,27 @@ sub process_request {
 | 
			
		||||
    my $typetab=xCAT::Table->new("nodetype",-create=>1);
 | 
			
		||||
    $typetab->setNodeAttribs($node,{arch=>$request->{arch}->[0]});
 | 
			
		||||
  }
 | 
			
		||||
  if (defined($request->{mac})) {
 | 
			
		||||
    my $mactab = xCAT::Table->new("mac",-create=>1);
 | 
			
		||||
    my @ifinfo;
 | 
			
		||||
    my $macstring = "";
 | 
			
		||||
    foreach (@{$request->{mac}}) {
 | 
			
		||||
       @ifinfo = split /\|/;
 | 
			
		||||
       if ($ifinfo[3]) {
 | 
			
		||||
          (my $ip,my $netbits) = split /\//,$ifinfo[3];
 | 
			
		||||
	  if ($ip =~ /\d+\.\d+\.\d+\.\d+/) {
 | 
			
		||||
	  	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]);
 | 
			
		||||
		if ($hosttag) {
 | 
			
		||||
		   $macstring .= $ifinfo[2]."!".$hosttag."|";
 | 
			
		||||
		}
 | 
			
		||||
	  }
 | 
			
		||||
       }
 | 
			
		||||
    }
 | 
			
		||||
    $mactab->setNodeAttribs($node,{mac=>$macstring});
 | 
			
		||||
  }
 | 
			
		||||
  #TODO: mac table?  on the one hand, 'the' definitive interface was determined earlier...
 | 
			
		||||
  #Delete the state it was in to make it traverse destiny once agoin
 | 
			
		||||
  my $chaintab = xCAT::Table->new('chain');
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user