#!/usr/bin/perl -wT use English; use Fcntl ':flock'; # # Suck out virtual names and create CNAME map entries. # # This script always does the right thing, so it does not matter who calls it. # # usage: named_setup # # # Configure variables # my $TB = "@prefix@"; my $TBOPS = "@TBOPSEMAIL@"; my $mapdir = "/etc/namedb"; my $mapfile = "$mapdir/emulab.db"; my $mapfileback = "$mapdir/emulab.db.backup"; my $mapfilehead = "$mapdir/emulab.db.head"; my $mapfiletail = "$mapdir/emulab.db.tail"; my $lockfile = "/var/tmp/testbed_named_lockfile"; my $dbg = 0; my @row; # # We don't want to run this script unless its the real version. # if ($EUID != 0) { die("Must be root! Maybe its a development version?"); } # XXX Hacky! if ($TB ne "/usr/testbed") { die("Wrong version. Maybe its a development version?"); } # un-taint path $ENV{'PATH'} = '/bin:/usr/bin:/usr/sbin:/usr/local/bin'; delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'}; # # Turn off line buffering on output # $| = 1; # # Testbed Support libraries # push(@INC, "$TB/lib"); require libtestbed; require libdb; # # We need to serialize this script to avoid a trashed map file. Use # a dummy file in /var/tmp, opened for writing and flock'ed. # open(LOCK, ">>$lockfile") || fatal("Couldn't open $lockfile\n"); $count = 0; while (flock(LOCK, LOCK_EX|LOCK_NB) == 0) { print "Another named map update in progress. Waiting a moment ...\n"; if ($count++ > 20) { fatal("Could not get the lock after a long time!\n"); } sleep(1); } # # We stick the new map entries into the tail file. First zero it out. # open(MAP, ">$mapfiletail") || fatal("Couldn't open $mapfiletail\n"); print MAP "\n"; print MAP ";\n"; print MAP "; DO NOT EDIT below this point. Auto generated map entries!\n"; print MAP ";\n"; print MAP "\n"; print MAP "\$TTL\t1\n"; # # Figure out the set of nodes we are working on. These are the nodes # that have a vname in the reserved table. # $db_result = DBQueryFatal("select node_id,pid,eid,vname from reserved where vname!=''"); if ($db_result->numrows > 0) { # # Create a CNAME for each reserved node. # while (@row = $db_result->fetchrow_array) { my $node_id = $row[0]; my $pid = $row[1]; my $eid = $row[2]; my $vname = $row[3]; my $cname = sprintf("%-40s", "$vname.$eid.$pid"); printf MAP "$cname IN\tCNAME\t$node_id\n"; } } print MAP "\n"; close(MAP); # # Concat the head and tail files to create the new map. # if (-e $mapfile) { system("mv $mapfile $mapfileback") == 0 or fatal("Could not back up $mapfile to $mapfileback\n"); } # # Generate a warning so that no one tries to edit the file by hand # open(MAP, ">$mapfile") || fatal("Couldn't open $mapfile\n"); print MAP ";\n". "; ******************************************************************\n". "; DO NOT EDIT THIS FILE. IT IS A CREATION, A FIGMENT, A CONTRIVANCE!\n". ";\n". "; Edit the \"head\" file, then run ${TB}bin/named_setup.\n". "; ******************************************************************\n". ";\n"; # # Now copy in the head part of the map, looking for the serial # number so it can be bumped up. # open(MAPHEAD, "<$mapfilehead") || fatal("Couldn't open $mapfilehead\n"); while () { if ( /Serial Number/i ) { my $serial = `date +%s`; chop $serial; print MAP "\t\t\t$serial\t; Serial Number -- DO NOT EDIT\n"; } else { print MAP "$_"; } } close(MAPHEAD); close(MAP); # # Now the tail of the map. # system("cat $mapfiletail >> $mapfile") == 0 or fatal("Failed to concat $mapfiletail to $mapfile\n"); # # This is better than HUPing the nameserver. # system("named.reload > /dev/null") == 0 or fatal("named.reload failed!\n"); exit(0); sub fatal { local($msg) = $_[0]; SENDMAIL($TBOPS, "TESTBED: Named Setup Failed", $msg); die($msg); }