-Nearly complete DNS handler

git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@5488 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd
This commit is contained in:
jbjohnso 2010-03-16 20:36:25 +00:00
parent 6a2947a492
commit d36029ab1b

View File

@ -159,7 +159,7 @@ sub process_request {
}
#We manipulate local namedconf
$ctx->{dbdir} = get_dbdir();
update_namedconf($ctx);
update_namedconf($ctx);
update_zones($ctx);
if ($ctx->{restartneeded}) {
system("/sbin/service named start");
@ -171,6 +171,8 @@ sub process_request {
}
}
#now we stick to Net::DNS style updates, with TSIG if possible. TODO: kerberized (i.e. Windows) DNS server support, maybe needing to use nsupdate -g....
$ctx->{resolver} = Net::DNS::Resolver->new();
add_records($ctx);
}
sub get_dbdir {
@ -191,12 +193,27 @@ sub update_zones {
my $dbdir = $ctx->{dbdir};
my $domain = $ctx->{domain};
my $name = hostname;
my $node = $name;
unless ($domain =~ /^\./) {
$domain = '.'.$domain;
}
unless ($name =~ /\./) {
$name .= $domain;
}
unless ($name =~ /\.\z/) {
$name .= '.';
}
my $ip=$node;
if ($ctx->{hoststab} and $ctx->{hoststab}->{$node} and $ctx->{hoststab}->{$node}->[0]->{ip}) {
$ip = $ctx->{hoststab}->{$node}->[0]->{ip};
} else {
unless ($ip = inet_aton($ip)) {
print "Unable to find an IP for $node in hosts table or via system lookup (i.e. /etc/hosts";
sendmsg([1,"Unable to find an IP for $node in hosts table or via system lookup (i.e. /etc/hosts"]);
next;
}
$ip = inet_ntoa($ip);
}
my @neededzones = keys %{$ctx->{zonestotouch}};
push @neededzones,keys %{$ctx->{adzones}};
my ($sec, $min, $hour, $mday, $mon, $year, $rest) = localtime(time);
@ -213,6 +230,9 @@ sub update_zones {
print $zonehdl '$TTL 86400'."\n";
print $zonehdl '@ IN SOA '.$name." root.$name ( $serial 10800 3600 604800 86400 )\n";
print $zonehdl " IN NS $name\n";
if ($name =~ /$currzone/) { #Must guarantee an A record for the DNS server
print $zonehdl "$name IN A $ip\n";
}
close($zonehdl);
$ctx->{restartneeded}=1;
}
@ -405,8 +425,16 @@ sub add_records {
}
my $node;
my $ip;
my $domain = $ctx->{domain}; # store off for lazy typing and possible local mangling
unless ($domain =~ /^\./) { $domain = '.'.$domain; } #example.com becomes .example.com for consistency
$ctx->{nsmap} = {}; #will store a map to known NS records to avoid needless redundant queries to sort nodes into domains
$ctx->{updatesbyzone}={}; #sort all updates into their respective zones for bulk update for fewer DNS transactions
foreach $node (@{$ctx->{nodes}}) {
$ip = $node;
my $name = $node;
unless ($name =~ /$domain/) { $name .= $domain } # $name needs to represent fqdn, but must preserve $node as a nodename for cfg lookup
#if (domaintab->{$node}->[0]->{domain) { $domain = domaintab->{$node}->[0]->{domain) }
#above is TODO draft of how multi-domain support could come into play
if ($ctx->{hoststab} and $ctx->{hoststab}->{$node} and $ctx->{hoststab}->{$node}->[0]->{ip}) {
$ip = $ctx->{hoststab}->{$node}->[0]->{ip};
} else {
@ -416,22 +444,70 @@ sub add_records {
}
$ip = inet_ntoa($ip);
}
$ctx->{currip}=$ip;
#time to update, A and PTR records, IPv6 still TODO
$ip = reverse(split(/\./,$ip));
$ip = join('.',reverse(split(/\./,$ip)));
$ip .= '.IN-ADDR.ARPA.';
#ok, now it is time to identify which zones should actually hold the forward (A) and reverse (PTR) records and a nameserver to handle the request
my $revzone = $ip;
$ctx->{currnode}=$node;
$ctx->{currname}=$name;
$ctx->{currrevname}=$ip;
find_nameserver_for_dns($ctx,$revzone);
find_nameserver_for_dns($ctx,$domain);
}
my $zone;
foreach $zone (keys %{$ctx->{updatesbyzone}}) {
my $resolver = Net::DNS::Resolver->new(nameservers=>[$ctx->{nsmap}->{$zone}]);
my $update = Net::DNS::Update->new($zone);
foreach (@{$ctx->{updatesbyzone}->{$zone}}) {
$update->push(update=>rr_add($_));
}
$update->sign_tsig("xcat_key",$ctx->{privkey});
my $reply = $resolver->send($update);
print Dumper($reply);
}
}
my $resolver = Net::DNS::Resolver->new;
my $key_name = 'xcat_key';
my $key = 'UlpPekE5Zmg0VzBsbTA2alZSRkxWMGRWTDZRckhJaHM=';
my $update = Net::DNS::Update->new();
$update->push(update => rr_add('bar.xcat.e1350 A 172.16.0.21'));
$update->sign_tsig($key_name,$key);
my $reply = $resolver->send($update);
print Dumper($reply);
$update = Net::DNS::Update->new('16.172.IN-ADDR.ARPA');
$update->push(update => rr_add('21.0.16.172.IN-ADDR.ARPA. IN PTR foo.xcat.e1350.'));
$update->sign_tsig($key_name,$key);
$reply = $resolver->send($update);
print Dumper($reply);
#process_request({node=>['noctilucent','bmc1','n1','switch1']});
sub find_nameserver_for_dns {
my $ctx = shift;
my $zone = shift;
my $node = $ctx->{currnode};
my $ip = $ctx->{currip};
my $rname = $ctx->{currrevname};
my $name = $ctx->{currname};
unless ($name =~ /\.\z/) { $name .= '.' }
my $rrcontent = "$name IN A $ip";
if ($zone =~ /IN-ADDR.ARPA/) { #reverse style
$rrcontent = "$rname IN PTR $name";
}
while ($zone) {
unless (defined $ctx->{nsmap}->{$zone}) { #ok, we already thought about this zone and made a decision
print $zone."\n";
my $reply = $ctx->{resolver}->query($zone,'NS');
if ($reply) {
foreach my $record ($reply->answer) {
$ctx->{nsmap}->{$zone} = $record->nsdname;
}
} else {
$ctx->{nsmap}->{$zone} = 0;
}
}
if ($ctx->{nsmap}->{$zone}) { #we have a nameserver for this zone, therefore this zone is one to update
if ($ctx->{updatesbyzone}->{$zone}) { #attach to existing list of updates
push @{$ctx->{updatesbyzone}->{$zone}},$rrcontent;
} else { #create a new list.
$ctx->{updatesbyzone}->{$zone} = [ $rrcontent ];
}
last;
} else { #we have it defined, but zero, means search higher domains. Possible to shortcut further by pointing to the right domain, maybe later
$zone =~ s/^[^\.]*\.//; #strip all up to and including first dot
unless ($zone) {
sendmsg([1,"Unable to find reverse lookup zone to hold $ip"],$node);
last;
}
}
}
}
sub sendmsg {
print Dumper(@_);
}