Commit 3285bc3e authored by Leigh Stoller's avatar Leigh Stoller

Lots of little changes for sending email to the right places, with

proper headers. Split out some of the mail into testbed-logs,
testbed-ops, and testbed-approval. Added a library for including from
our perl scripts. Contains a couple of mail helper functions, but will
hopefully contain more as time goes by.

Fixed a bug in the web interface that was causing breakage for people
with multiple accounts. Mac and Jay have noticed this, when logging
out and trying to join or create a project under a new or different
name.
parent ab0486e5
...@@ -24,7 +24,7 @@ LIBEXEC_STUFF = mkprojdir rmproj mkacct-ctrl rmacct-ctrl \ ...@@ -24,7 +24,7 @@ LIBEXEC_STUFF = mkprojdir rmproj mkacct-ctrl rmacct-ctrl \
os_setup mkexpdir console_setup webnscheck \ os_setup mkexpdir console_setup webnscheck \
webstartexp webendexp webbatchexp webkillbatchexp webstartexp webendexp webbatchexp webkillbatchexp
LIB_STUFF = libtbsetup.pm LIB_STUFF = libtbsetup.pm libtestbed.pm
# #
# Force dependencies on the scripts so that they will be rerun through # Force dependencies on the scripts so that they will be rerun through
......
...@@ -23,6 +23,7 @@ my $optlist = "d"; ...@@ -23,6 +23,7 @@ my $optlist = "d";
my $TB = "@prefix@"; my $TB = "@prefix@";
my $DBNAME = "@TBDBNAME@"; my $DBNAME = "@TBDBNAME@";
my $TBOPS = "@TBOPSEMAIL@"; my $TBOPS = "@TBOPSEMAIL@";
my $TBLOGS = "@TBLOGSEMAIL@";
my $tbbindir = "$TB/bin/"; my $tbbindir = "$TB/bin/";
my $batchdir = "$TB/batch"; my $batchdir = "$TB/batch";
...@@ -42,7 +43,7 @@ my $eid; ...@@ -42,7 +43,7 @@ my $eid;
my $pid; my $pid;
my $logname; my $logname;
my $nsfile; my $nsfile;
my $user_name = "Batch Daemon"; my $user_name = "Testbed Operations";
my $user_email = "$TBOPS"; my $user_email = "$TBOPS";
# #
...@@ -50,6 +51,12 @@ my $user_email = "$TBOPS"; ...@@ -50,6 +51,12 @@ my $user_email = "$TBOPS";
# #
$| = 1; $| = 1;
#
# Testbed Support library
#
push(@INC, "$TB/lib");
require libtestbed;
# #
# Untaint the path # Untaint the path
# #
...@@ -544,50 +551,47 @@ sub email_status($) ...@@ -544,50 +551,47 @@ sub email_status($)
sub notify_user($$$) sub notify_user($$$)
{ {
my($mesg, $subline, $iserr) = @_; my($mesg, $subtext, $iserr) = @_;
my($to,$cc); my $subject, $from, $to, $cc;
my $MAIL;
print STDOUT "$mesg\n"; print STDOUT "$mesg\n";
# $subject = "TESTBED: Batch Mode Experiment $subtext $pid/$eid";
# If an error, goes to TBOPS and is CC'ed to user. $from = $TBOPS;
# Otherwise goes to user and is CC'ed to TBOPS $to = "$user_name <$user_email>";
#
if ($iserr) { if ($iserr) {
$to = $TBOPS; $cc = "Cc: $TBOPS";
$cc = $user_email;
} }
else { else {
$to = $user_email; $cc = "Bcc: $TBLOGS";
$cc = $TBOPS;
} }
open(MAIL, "| /usr/bin/mail ". if (! ($MAIL = OPENMAIL($to, $subject, $from, $cc))) {
"-s \"TESTBED: Batch Mode Experiment $subline $pid/$eid\" ". die("Cannot start mail program!");
"-c $cc $to >/dev/null 2>&1") }
or die "Cannot start mail program: $!";
print MAIL $mesg; print $MAIL $mesg;
if (defined($logname) && open(IN, "$logname")) { if (defined($logname) && open(IN, "$logname")) {
print MAIL "\n\n---------\n\n"; print $MAIL "\n\n---------\n\n";
while (<IN>) { while (<IN>) {
print MAIL "$_"; print $MAIL "$_";
} }
close(IN); close(IN);
} }
if (defined($nsfile) && open(IN, "$nsfile")) { if (defined($nsfile) && open(IN, "$nsfile")) {
print MAIL "\n\n---------\n\n"; print $MAIL "\n\n---------\n\n";
while (<IN>) { while (<IN>) {
print MAIL "$_"; print $MAIL "$_";
} }
close(IN); close(IN);
} }
close(MAIL); close($MAIL);
} }
# #
......
...@@ -19,7 +19,6 @@ my $optlist = ""; ...@@ -19,7 +19,6 @@ my $optlist = "";
# #
my $TB = "@prefix@"; my $TB = "@prefix@";
my $DBNAME = "@TBDBNAME@"; my $DBNAME = "@TBDBNAME@";
my $TBOPS = "@TBOPSEMAIL@";
my $tbbindir = "$TB/bin/"; my $tbbindir = "$TB/bin/";
my $batchdir = "$TB/batch"; my $batchdir = "$TB/batch";
......
...@@ -27,6 +27,7 @@ my $optlist = "b"; ...@@ -27,6 +27,7 @@ my $optlist = "b";
my $TB = "@prefix@"; my $TB = "@prefix@";
my $DBNAME = "@TBDBNAME@"; my $DBNAME = "@TBDBNAME@";
my $TBOPS = "@TBOPSEMAIL@"; my $TBOPS = "@TBOPSEMAIL@";
my $TBLOGS = "@TBLOGSEMAIL@";
my $tbdir = "$TB/bin/"; my $tbdir = "$TB/bin/";
my $projroot = "/proj"; my $projroot = "/proj";
...@@ -45,6 +46,12 @@ delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'}; ...@@ -45,6 +46,12 @@ delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
# #
$| = 1; $| = 1;
#
# Testbed Support library
#
push(@INC, "$TB/lib");
require libtestbed;
# #
# Parse command arguments. Once we return from getopts, all that should # Parse command arguments. Once we return from getopts, all that should
# left are the required arguments. # left are the required arguments.
...@@ -229,26 +236,27 @@ if ($batch) { ...@@ -229,26 +236,27 @@ if ($batch) {
# #
# Send email notification if not in batch mode. # Send email notification if not in batch mode.
# #
open(MAIL, "| /usr/bin/mail ". if (! ($MAIL = OPENMAIL("$user_name <$user_email>",
"-s \"TESTBED: Experiment $pid/$eid Terminated\" ". "TESTBED: Experiment $pid/$eid Terminated",
"-c $TBOPS \"$user_name <$user_email>\" >/dev/null 2>&1") undef, "Bcc: $TBLOGS"))) {
or die "Cannot start mail program: $!"; die("Cannot start mail program!");
}
print MAIL "Experiment `$eid' in project `$pid' has been terminated.\n";
print MAIL "You may now reuse `$eid' as an experiment name.\n\n"; print $MAIL "Experiment `$eid' in project `$pid' has been terminated.\n";
print MAIL "Appended below is the output of the experiment teardown.\n"; print $MAIL "You may now reuse `$eid' as an experiment name.\n\n";
print MAIL "If you have any questions or comments, please include the\n"; print $MAIL "Appended below is the output of the experiment teardown.\n";
print MAIL "output below in your message to $TBOPS\n"; print $MAIL "If you have any questions or comments, please include the\n";
print MAIL "\n\n---------\n\n"; print $MAIL "output below in your message to $TBOPS\n";
print $MAIL "\n\n---------\n\n";
if (open(IN, "$logname")) { if (open(IN, "$logname")) {
while (<IN>) { while (<IN>) {
print MAIL "$_"; print $MAIL "$_";
} }
close(IN); close(IN);
} }
close(MAIL); close($MAIL);
unlink("$logname"); unlink("$logname");
exit 0; exit 0;
...@@ -256,7 +264,8 @@ exit 0; ...@@ -256,7 +264,8 @@ exit 0;
sub fatal() sub fatal()
{ {
my($mesg) = $_[0]; my($mesg) = $_[0];
local $MAIL;
print STDOUT $mesg; print STDOUT $mesg;
# #
...@@ -270,22 +279,23 @@ sub fatal() ...@@ -270,22 +279,23 @@ sub fatal()
# Send a message to the testbed list. Append the logfile if it got # Send a message to the testbed list. Append the logfile if it got
# that far. # that far.
# #
open(MAIL, "| /usr/bin/mail ". if (! ($MAIL = OPENMAIL("$user_name <$user_email>",
"-s \"TESTBED: Termination Failure $pid/$eid\" ". "TESTBED: Termination Failure: $pid/$eid",
"$TBOPS >/dev/null 2>&1") undef, "Cc: $TBOPS"))) {
or die "Cannot start mail program: $!"; die("Cannot start mail program!");
}
print MAIL $mesg; print $MAIL $mesg;
if (open(IN, "$logname")) { if (open(IN, "$logname")) {
print MAIL "\n\n---------\n\n"; print $MAIL "\n\n---------\n\n";
while (<IN>) { while (<IN>) {
print MAIL "$_"; print $MAIL "$_";
} }
close(IN); close(IN);
} }
close(MAIL); close($MAIL);
unlink("$logname"); unlink("$logname");
exit(-1); exit(-1);
......
...@@ -44,6 +44,12 @@ delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'}; ...@@ -44,6 +44,12 @@ delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
$| = 1; #Turn off line buffering on output $| = 1; #Turn off line buffering on output
#
# Testbed Support library
#
push(@INC, "$TB/lib");
require libtestbed;
# #
# Set up for querying the database. # Set up for querying the database.
# #
...@@ -198,8 +204,7 @@ exit(0); ...@@ -198,8 +204,7 @@ exit(0);
sub fatal { sub fatal {
local($msg) = $_[0]; local($msg) = $_[0];
system("echo \"$msg\" | /usr/bin/mail ". SENDMAIL($TBOPS, "TESTBED: Exports Setup Failed", $msg);
"-s 'TESTBED: Named Setup Failed' $TBOPS");
die($msg); die($msg);
} }
......
...@@ -30,6 +30,12 @@ my $projroot = "/proj"; ...@@ -30,6 +30,12 @@ my $projroot = "/proj";
# #
$| = 1; $| = 1;
#
# Testbed Support library
#
push(@INC, "$TB/lib");
require libtestbed;
# #
# Untaint the path # Untaint the path
# #
...@@ -144,13 +150,8 @@ sub fatal($) ...@@ -144,13 +150,8 @@ sub fatal($)
# #
# Send a message to the testbed list # Send a message to the testbed list
# #
open(MAIL, "| /usr/bin/mail ". SENDMAIL($TBOPS,
"-s \"TESTBED: Batch Mode Cancelation Failure $pid/$eid\" ". "TESTBED: Batch Mode Cancelation Failure $pid/$eid", $mesg);
"$TBOPS >/dev/null 2>&1")
or die "Cannot start mail program: $!";
print MAIL $mesg;
close(MAIL);
exit(-1); exit(-1);
} }
......
#!/usr/bin/perl -w
use English;
#
# A library of useful stuff.
#
#
# Send an email message via sendmail -t.
#
# I am mimicking the PHP mail interface, only because I'm old and its
# hard to remember new things. I did add a From arg since thats basically
# required to make the mail look nice (not generated by root or daemon!).
#
# SENDMAIL(To, Subject, Message, [From], [More Headers])
#
sub SENDMAIL($$$;$$)
{
my($To, $Subject, $Message, $From, $Headers) = @_;
if (! open(MAIL, "|/usr/sbin/sendmail -t")) {
print STDERR "SENDMAIL: Could not start sendmail: $!\n";
return 0;
}
#
# Sendmail will figure this out if not given.
#
if (defined($From) && $From) {
print MAIL "From: $From\n";
}
print MAIL "To: $To\n";
print MAIL "Subject: $Subject\n";
if (defined($Headers)) {
print MAIL "$Headers\n";
}
print MAIL "\n";
print MAIL "$Message\n";
print MAIL "\n";
if (! close(MAIL)) {
print STDERR "SENDMAIL: Could not finish sendmail: $!\n";
return 0;
}
return 1;
}
#
# Fire up a sendmail process, and return the handle for the caller
# to print the body of the message into. This is easer in many places.
#
# OPENMAIL(To, Subject, [From], [More Headers])
#
sub OPENMAIL($$;$$)
{
my($To, $Subject, $From, $Headers) = @_;
local *MAIL;
if (! open(MAIL, "|/usr/sbin/sendmail -t")) {
print STDERR "OPENMAIL: Could not start sendmail: $!\n";
return 0;
}
#
# Sendmail will figure this out if not given.
#
if (defined($From) && $From) {
print MAIL "From: $From\n";
}
print MAIL "To: $To\n";
print MAIL "Subject: $Subject\n";
if (defined($Headers)) {
print MAIL "$Headers\n";
}
print MAIL "\n";
return(*MAIL);
}
1;
...@@ -13,6 +13,7 @@ use Fcntl ':flock'; ...@@ -13,6 +13,7 @@ use Fcntl ':flock';
# #
my $TB = "@prefix@"; my $TB = "@prefix@";
my $DBNAME = "@TBDBNAME@"; my $DBNAME = "@TBDBNAME@";
my $TBOPS = "@TBOPSEMAIL@";
my $mapdir = "/etc/namedb"; my $mapdir = "/etc/namedb";
my $mapfile = "$mapdir/emulab.db"; my $mapfile = "$mapdir/emulab.db";
...@@ -40,6 +41,12 @@ delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'}; ...@@ -40,6 +41,12 @@ delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
$| = 1; #Turn off line buffering on output $| = 1; #Turn off line buffering on output
#
# Testbed Support library
#
push(@INC, "$TB/lib");
require libtestbed;
# #
# Set up for querying the database. # Set up for querying the database.
# #
...@@ -158,7 +165,6 @@ exit(0); ...@@ -158,7 +165,6 @@ exit(0);
sub fatal { sub fatal {
local($msg) = $_[0]; local($msg) = $_[0];
system("echo \"$msg\" | /usr/bin/mail ". SENDMAIL($TBOPS, "TESTBED: Named Setup Failed", $msg);
"-s 'TESTBED: Named Setup Failed' testbed-ops\@fast.cs.utah.edu");
die($msg); die($msg);
} }
...@@ -199,7 +199,7 @@ sub RebootNode { ...@@ -199,7 +199,7 @@ sub RebootNode {
$syspid = fork(); $syspid = fork();
if ($syspid) { if ($syspid) {
local $SIG{ALRM} = sub { kill("TERM", $syspid); }; local $SIG{ALRM} = sub { kill("TERM", $syspid); };
alarm 30; alarm 20;
waitpid($syspid, 0); waitpid($syspid, 0);
alarm 0; alarm 0;
......
...@@ -29,7 +29,6 @@ my $TBOPS = "@TBOPSEMAIL@"; ...@@ -29,7 +29,6 @@ my $TBOPS = "@TBOPSEMAIL@";
my $nodereboot = "$TB/bin/node_reboot"; my $nodereboot = "$TB/bin/node_reboot";
my $ping = "/sbin/ping"; my $ping = "/sbin/ping";
my $mail = "/usr/bin/mail";
my $dbg = 0; my $dbg = 0;
my @nodes = (); my @nodes = ();
my %osid = (); my %osid = ();
...@@ -51,6 +50,12 @@ delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'}; ...@@ -51,6 +50,12 @@ delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
$| = 1; #Turn off line buffering on output $| = 1; #Turn off line buffering on output
#
# Testbed Support library
#
push(@INC, "$TB/lib");
require libtestbed;
# #
# Parse command arguments. Once we return from getopts, all that should be # Parse command arguments. Once we return from getopts, all that should be
# left are the required arguments. # left are the required arguments.
...@@ -226,14 +231,13 @@ foreach my $node ( @nodes ) { ...@@ -226,14 +231,13 @@ foreach my $node ( @nodes ) {
} }
# Send mail to testbed-ops about it # Send mail to testbed-ops about it
open(MAIL,"| $mail -s \"TESTBED: $node down?\" $TBOPS"); SENDMAIL($TBOPS, "TESTBED: Node $node is down",
print MAIL "User ".getpwuid($UID)." was running expt. $eid\n"; "User ".getpwuid($UID)." was running expt. $eid\n".
print MAIL "in proj. $pid using ir file /proj/$pid/exp/$eid/tbdata\n"; "in proj. $pid using ir file /proj/$pid/exp/$eid/tbdata\n".
print MAIL "but $node appears to be unresponsive.\n"; "but $node appears to be unresponsive.\n\n".
print MAIL "\nPlease look into this matter. $node has been reserved to\n"; "Please look into this matter. $node has been reserved to\n".
print MAIL "the testbed/down experiment until this has been resolved.\n\n"; "the testbed/down experiment until this has been resolved.\n\n".
print MAIL "Thanks,\nTestbed Operations\ntestbed-ops\@flux.cs.utah.edu\n"; "Thanks,\n");
close(MAIL);
die("Oops, $node did not come back alive!\n"); die("Oops, $node did not come back alive!\n");
} }
......
...@@ -43,6 +43,12 @@ $| = 1; ...@@ -43,6 +43,12 @@ $| = 1;
$ENV{'PATH'} = "/bin:/usr/bin:"; $ENV{'PATH'} = "/bin:/usr/bin:";
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'}; delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
#
# Testbed Support library
#
push(@INC, "$TB/lib");
require libtestbed;
# #
# Parse command arguments. Once we return from getopts, all that should be # Parse command arguments. Once we return from getopts, all that should be
# left are the required arguments. # left are the required arguments.
...@@ -196,8 +202,7 @@ sub DBquery($) ...@@ -196,8 +202,7 @@ sub DBquery($)
sub fatal { sub fatal {
local($msg) = $_[0]; local($msg) = $_[0];
system("echo \"$msg\" | /usr/bin/mail ". SENDMAIL($TBOPS, "TESTBED: Reload Daemon Died", $msg);
"-s 'TESTBED: Reload Daemon Died' $TBOPS");
die($msg); die($msg);
} }
......
...@@ -30,6 +30,7 @@ my $optlist = "b:"; ...@@ -30,6 +30,7 @@ my $optlist = "b:";
my $TB = "@prefix@"; my $TB = "@prefix@";
my $DBNAME = "@TBDBNAME@"; my $DBNAME = "@TBDBNAME@";
my $TBOPS = "@TBOPSEMAIL@"; my $TBOPS = "@TBOPSEMAIL@";
my $TBLOGS = "@TBLOGSEMAIL@";
my $TBINFO = "$TB/expinfo"; my $TBINFO = "$TB/expinfo";
my $tbdir = "$TB/bin/"; my $tbdir = "$TB/bin/";
...@@ -57,6 +58,12 @@ $| = 1; ...@@ -57,6 +58,12 @@ $| = 1;
$ENV{'PATH'} = '/bin:/usr/bin'; $ENV{'PATH'} = '/bin:/usr/bin';
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'}; delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
#
# Testbed Support library
#
push(@INC, "$TB/lib");
require libtestbed;
# #
# Parse command arguments. Once we return from getopts, all that should # Parse command arguments. Once we return from getopts, all that should
# left are the required arguments. # left are the required arguments.
...@@ -136,9 +143,9 @@ if ($query_result->numrows < 1) { ...@@ -136,9 +143,9 @@ if ($query_result->numrows < 1) {
} }
@row = $query_result->fetchrow_array(); @row = $query_result->fetchrow_array();
if ($row[0]) { if ($row[0]) {
fatal("Experiment $pid/$eid is already configured!\n". die("Experiment $pid/$eid is already configured!\n".
"You are not allowed to reconfigure experiments unless you\n". "You are not allowed to reconfigure experiments unless you\n".
"first terminate the existing experiment via the web interface.\n"); "first terminate the existing experiment via the web interface.\n");
} }
# #
...@@ -308,56 +315,58 @@ if ($batch) { ...@@ -308,56 +315,58 @@ if ($batch) {
# #
# Dump the report file and the log file to the user via email. # Dump the report file and the log file to the user via email.
# #
open(MAIL, "| /usr/bin/mail ". if (! ($MAIL = OPENMAIL("$user_name <$user_email>",
"-s \"TESTBED: New Experiment Created: $pid/$eid\" ". "TESTBED: New Experiment Created: $pid/$eid",
"-c $TBOPS \"$user_name <$user_email>\" >/dev/null 2>&1") undef, "Bcc: $TBLOGS"))) {
or die "Cannot start mail program: $!"; tbendit();
die("Cannot start mail program!");
print MAIL "Your experiment `$eid' in project `$pid' is now configured.\n"; }
print MAIL "Here is the experiment summary detailing the nodes that were\n";
print MAIL "allocated to you. You may use the `Qualified Name' to log on\n"; print $MAIL "Your experiment `$eid' in project `$pid' is now configured.\n";
print MAIL "to your nodes. See /etc/hosts on your nodes (when running\n"; print $MAIL "Here is the experiment summary detailing the nodes that were\n";
print MAIL "FreeBSD, Linux, or NetBSD) for the IP name mapping on each node\n"; print $MAIL "allocated to you. You may use the `Qualified Name' to log on\n";
print $MAIL "to your nodes. See /etc/hosts on your nodes (when running\n";
print MAIL "\n"; print $MAIL "FreeBSD, Linux, or NetBSD) for the IP mapping on each node\n";
print MAIL "User: $user_name\n";
print MAIL "EID: $eid\n"; print $MAIL "\n";
print MAIL "PID: $pid\n"; print $MAIL "User: $user_name\n";
print MAIL "Name: $expt_name\n"; print $MAIL "EID: $eid\n";
print MAIL "Created: $expt_created\n"; print $MAIL "PID: $pid\n";
print MAIL "Expires: $expt_expires\n"; print $MAIL "Name: $expt_name\n";
print MAIL "Directory: $eiddir\n\n"; print $MAIL "Created: $expt_created\n";
print $MAIL "Expires: $expt_expires\n";
print $MAIL "Directory: $eiddir\n\n";
if (open(IN, "$repfile")) { if (open(IN, "$repfile")) {
while (<IN>) { while (<IN>) {
print MAIL "$_"; print $MAIL "$_";
} }
close(IN); close(IN);
} }
print MAIL "\n\n---------\n\n"; print $MAIL "\n\n---------\n\n";
print MAIL "Here is the log of the configuration process.\n"; print $MAIL "Here is the log of the configuration process.\n";
print MAIL "If you have any questions or problems, please include the\n"; print $MAIL "If you have any questions or problems, please include the\n";
print MAIL "output below in your message to $TBOPS\n\n"; print $MAIL "output below in your message to $TBOPS\n\n";
if (open(IN, "$logname")) { if (open(IN, "$logname")) {
while (<IN>) { while (<IN>) {
print MAIL "$_"; print $MAIL "$_";
} }
close(IN); close(IN);
} }
if (open(IN, "$nsfile")) { if (open(IN, "$nsfile")) {
print MAIL "\n\n---------\n\n"; print $MAIL "\n\n---------\n\n";
print MAIL "Here is the NS file\n\n"; print $MAIL "Here is the NS file\n\n";
while (<IN>) { while (<IN>) {
print MAIL "$_"; print $MAIL "$_";
} }
close(IN); close(IN);
} }
close(MAIL); close($MAIL);
unlink("$tempns"); unlink("$tempns");
unlink("$logname"); unlink("$logname");
...@@ -366,6 +375,7 @@ exit 0; ...@@ -366,6 +375,7 @@ exit 0;
sub fatal() sub fatal()
{ {
my($mesg) = $_[0];