Commit b437e338 authored by Leigh Stoller's avatar Leigh Stoller

Add new ntpstart file, intended to wrap up ntpd startup code, after

first talking to tmcd to get the ntpdrift and ntp server/peer lists.
This is a strict wrapper so it should be invoked from /etc/rc.conf
like this:

	xntpd_program="/usr/local/etc/emulab/ntpstart"
	xntpd_flags="/usr/sbin/ntpd -p /var/run/ntpd.pid"

which is to say that this program passes it entire argument list off
to the shell once it sets up the config file. We fire off ntp no
matter what happens though, and allow for no actual changes to the
config file if tmcd does not provide anything.

TMCD: Add ntpinfo and ntpdrift commands, as per Mike's specification.
ntpinfo returns lines like:
	SERVER=nnn.nnn.nnn.nnn
	...
	PEER=nnn.nnn.nnn.nnn
	...
	DRIFT=nnn.nn

and "ntpdrift nnn.nn" allows the current drift setting to be placed
into the DB, although thats not currently happening. In the DB,
ntpdrift is a new float slot in the nodes table, that defaults to
NULL. The servers/peers are stored in a new table that looks like
this:

	+---------+---------+--------+
	| node_id | IP      | type   |
	+---------+---------+--------+
	| wa32    | 1.1.1.1 | server |
	| wa32    | 1.1.1.2 | server |
	| wa32    | 1.1.1.3 | peer   |
	| wa32    | 1.1.1.4 | peer   |
	+---------+---------+--------+
parent c1a97af3
#!/usr/bin/perl -w
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2002 University of Utah and the Flux Group.
# All rights reserved.
#
use English;
#
# Fire up ntp from /etc/rc. This is a strict wrapper so it should be
# invoked from /etc/rc.conf as such:
#
# xntpd_program="/usr/local/etc/emulab/ntpstart"
# xntpd_flags="/usr/sbin/ntpd -p /var/run/ntpd.pid"
#
# which is to say that this program passes it entire argument list to
# off to the shell once it sets up the config file. We fire off ntp
# no matter what happens though.
#
#
# Untaint path
#
$ENV{'PATH'} = '/bin:/sbin:/usr/bin:/usr/local/bin:/etc/testbed';
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
#
# Turn off line buffering on output
#
$| = 1;
#
# Load the OS independent support library. It will load the OS dependent
# library and initialize itself.
#
use lib "/usr/local/etc/emulab";
use libsetup;
# Locals
my @ntpinfo = ();
my $useold = 1;
my $newfile = "/tmp/ntp.conf.new";
my $ntpfile = "/etc/ntp.conf";
my $driftfile = "/etc/ntp.drift";
my $pidfile = "/var/run/ntpd.pid";
#
# Since this is a wrapper, we have to try to start ntp no matter what.
#
sub ntpstart () {
# system("ntpd @ARGV");
# return ($? >> 8);
print "ntpd @ARGV\n";
return 0;
}
#
# Ask for setup. If none then we are done. If provided with a drift value
# but no servers/peers, then need to leave the config alone and just
# replace the drift file.
#
my $TM = OPENTMCC("ntpinfo");
while (<$TM>) {
chomp();
if ($_ =~ /^PEER=.*$/ ||
$_ =~ /^SERVER=.*$/) {
$useold = 0;
}
push(@ntpinfo, $_);
}
CLOSETMCC($TM);
if (! @ntpinfo) {
exit(ntpstart());
}
#
# We are going to copy the old file to a new file, munging it as we go.
# Note that if the server did not provide any servers or peers, we want
# to use whatever is in the original file, but we still have to read it
# to find the name of the driftfile. So, just make a copy and throw it
# away later if it turns out we do not need a new version.
#
open(NEW, "> $newfile")
or fatal("Could not open $newfile: $!");
open(NTP, "< $ntpfile")
or fatal("Could not open $ntpfile: $!");
while (<NTP>) {
chomp();
SWITCH1: {
/^peer.*$/ && do {
last SWITCH1;
};
/^server.*$/ && do {
last SWITCH1;
};
/^driftfile[\s]*(\/.*)$/ && do {
$driftfile = $1;
};
print NEW "$_\n";
}
}
#
# Okay, now tack on the servers and peers to the new file. The drift
# goes into the driftfile.
#
foreach my $line (@ntpinfo) {
$_ = $line;
SWITCH1: {
/^PEER=(.*)$/ && do {
print NEW "peer $_\n";
last SWITCH1;
};
/^SERVER=(.*)$/ && do {
print NEW "server $_\n";
last SWITCH1;
};
/^DRIFT=(.*)$/ && do {
open(DRIFT, "> $driftfile");
print DRIFT "$1\n";
close(DRIFT);
last SWITCH1;
};
}
}
close(NTP)
or fatal("Could not close $ntpfile: $!");
close(NEW)
or fatal("Could not close $newfile: $!");
#
# If it turns out we want to use the old file (no servers/peers provided)
# then start ntp and exit. The new file is thrown away ...
#
if ($useold) {
exit(ntpstart());
}
#
# Okay, back up the old file and replace it with the new file!
#
system("cp -fp $ntpfile $ntpfile.old");
if ($?) {
fatal("Could not backup $ntpfile to $ntpfile.old\n");
}
system("cp -fp $newfile $ntpfile");
if ($?) {
fatal("Could not replace $ntpfile with $newfile\n");
}
exit(ntpstart());
#
# Print error and exit, but must start ntp anyway!
#
sub fatal($)
{
my ($msg) = @_;
print STDERR "*** $0:\n" .
" $msg\n";
exit(ntpstart());
}
......@@ -20,6 +20,8 @@
#include <assert.h>
#include <sys/wait.h>
#include <sys/fcntl.h>
#include <sys/syscall.h>
#include <sys/stat.h>
#include <paths.h>
#include <setjmp.h>
#include <mysql/mysql.h>
......@@ -124,6 +126,9 @@ COMMAND_PROTOTYPE(dotunnels);
COMMAND_PROTOTYPE(dovnodelist);
COMMAND_PROTOTYPE(doisalive);
COMMAND_PROTOTYPE(doipodinfo);
COMMAND_PROTOTYPE(doatarball);
COMMAND_PROTOTYPE(dontpinfo);
COMMAND_PROTOTYPE(dontpdrift);
struct command {
char *cmdname;
......@@ -158,6 +163,9 @@ struct command {
{ "vnodelist", dovnodelist},
{ "isalive", doisalive},
{ "ipodinfo", doipodinfo},
{ "ntpinfo", dontpinfo},
{ "ntpdrift", dontpdrift},
{ "tarball", doatarball},
};
static int numcommands = sizeof(command_array)/sizeof(struct command);
......@@ -3690,3 +3698,117 @@ COMMAND_PROTOTYPE(doipodinfo)
return 0;
}
/*
* Return ntp config for a node.
*/
COMMAND_PROTOTYPE(dontpinfo)
{
MYSQL_RES *res;
MYSQL_ROW row;
char buf[MYBUFSIZE];
int nrows;
if (!tcp) {
error("NTPINFO: %s: Cannot do this in UDP mode!\n", nodeid);
return 1;
}
/*
* Node is allowed to be free?
*/
/*
* First get the servers and peers.
*/
res = mydb_query("select type,IP from ntpinfo where node_id='%s'",
2, nodeid);
if (!res) {
error("NTPINFO: %s: DB Error getting ntpinfo!\n", nodeid);
return 1;
}
if ((nrows = (int)mysql_num_rows(res))) {
while (nrows) {
row = mysql_fetch_row(res);
if (row[0] && row[0][0] &&
row[1] && row[1][0]) {
if (!strcmp(row[0], "peer")) {
sprintf(buf, "PEER=%s\n", row[1]);
}
else {
sprintf(buf, "SERVER=%s\n", row[1]);
}
client_writeback(sock, buf, strlen(buf), tcp);
info("NTPINFO: %s", buf);
}
nrows--;
}
}
mysql_free_result(res);
/*
* Now get the drift.
*/
res = mydb_query("select ntpdrift from nodes "
"where node_id='%s' and ntpdrift is not null",
1, nodeid);
if (!res) {
error("NTPINFO: %s: DB Error getting ntpdrift!\n", nodeid);
return 1;
}
if ((int)mysql_num_rows(res)) {
row = mysql_fetch_row(res);
if (row[0] && row[0][0]) {
sprintf(buf, "DRIFT=%s\n", row[0]);
client_writeback(sock, buf, strlen(buf), tcp);
info("NTPINFO: %s", buf);
}
}
mysql_free_result(res);
return 0;
}
/*
* Upload the current ntp drift for a node.
*/
COMMAND_PROTOTYPE(dontpdrift)
{
float drift;
if (!tcp) {
error("NTPDRIFT: %s: Cannot do this in UDP mode!\n", nodeid);
return 1;
}
if (!islocal) {
error("NTPDRIFT: %s: remote nodes not allowed!\n", nodeid);
return 1;
}
/*
* Node can be free?
*/
if (sscanf(rdata, "%f", &drift) != 1) {
error("NTPDRIFT: %s: Bad argument\n", nodeid);
return 1;
}
mydb_update("update nodes set ntpdrift='%f' where node_id='%s'",
drift, nodeid);
return 0;
}
/*
* Return a tarball. Would work for rpms too. Anyway, it has to be a
* The tarball being requested has to be in the tarballs list for the
* node of course. Has to be a tcp connection of course, and all remote
* tcp connections are required to be ssl'ized.
*/
COMMAND_PROTOTYPE(doatarball)
{
return 0;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment