From 4982b9cdd96a4a6564d2288133985856e9938dfc Mon Sep 17 00:00:00 2001 From: David Johnson <johnsond@flux.utah.edu> Date: Thu, 16 Feb 2006 04:42:03 +0000 Subject: [PATCH] * Makeconf.in, configure, configure.in, defs-default, defs-johnsond-emulab: - added a new defs var, TBROBOCOPSEMAIL * tbsetup/power_mail.pm.in: - add some new info to robot powerup mails * db/libdb.pm.in: - add a new function to determine if an experiment contains nodes of a given class/type * tbsetup/swapexp.in: - check if exp is a robot exp; that is, if it has robots or motes; if so, cc error msgs to TBROBOCOPSEMAIL in addition to TBOPS --- Makeconf.in | 1 + configure | 24 +++++++++----- configure.in | 4 +++ db/libdb.pm.in | 29 ++++++++++++++++ defs-default | 1 + defs-johnsond-emulab | 1 + tbsetup/power_mail.pm.in | 71 +++++++++++++++++++++++++++++++++++----- tbsetup/swapexp.in | 23 ++++++++++++- 8 files changed, 135 insertions(+), 19 deletions(-) diff --git a/Makeconf.in b/Makeconf.in index 190d7b016c..a816f5ccb2 100644 --- a/Makeconf.in +++ b/Makeconf.in @@ -27,6 +27,7 @@ TBROOT = @prefix@ TBDBNAME = @TBDBNAME@ TBADMINGROUP = @TBADMINGROUP@ TBOPSEMAIL = @TBOPSEMAIL@ +TBROBOCOPSEMAIL = @TBROBOCOPSEMAIL@ TBLOGSEMAIL = @TBLOGSEMAIL@ TBAUDITEMAIL = @TBAUDITEMAIL@ TBACTIVEARCHIVE = @TBACTIVEARCHIVE@ diff --git a/configure b/configure index c445bbc4be..2a8080cdd9 100755 --- a/configure +++ b/configure @@ -1397,6 +1397,8 @@ done + + @@ -1610,6 +1612,8 @@ fi # TBOPSEMAIL_NOSLASH="$TBOPSEMAIL" TBOPSEMAIL="`echo $TBOPSEMAIL | sed -e 's/@/\\\@/'`" +TBROBOCOPSEMAIL_NOSLASH="$TBROBOCOPSEMAIL" +TBROBOCOPSEMAIL="`echo $TBROBOCOPSEMAIL | sed -e 's/@/\\\@/'`" TBLOGSEMAIL_NOSLASH="$TBLOGSEMAIL" TBLOGSEMAIL="`echo $TBLOGSEMAIL | sed -e 's/@/\\\@/'`" TBAUDITEMAIL_NOSLASH="$TBAUDITEMAIL" @@ -1947,17 +1951,17 @@ for ac_hdr in ulxmlrpcpp/ulxr_config.h do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:1951: checking for $ac_hdr" >&5 +echo "configure:1955: checking for $ac_hdr" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 1956 "configure" +#line 1960 "configure" #include "confdefs.h" #include <$ac_hdr> EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1961: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1965: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -1996,17 +2000,17 @@ for ac_hdr in linux/videodev.h do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:2000: checking for $ac_hdr" >&5 +echo "configure:2004: checking for $ac_hdr" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 2005 "configure" +#line 2009 "configure" #include "confdefs.h" #include <$ac_hdr> EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:2010: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:2014: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -2039,7 +2043,7 @@ done # Extract the first word of "gtk-config", so it can be a program name with args. set dummy gtk-config; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2043: checking for $ac_word" >&5 +echo "configure:2047: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_GTK_CONFIG'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2118,7 +2122,7 @@ fi # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # ./install, which can be erroneously created by make from ./install.sh. echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 -echo "configure:2122: checking for a BSD compatible install" >&5 +echo "configure:2126: checking for a BSD compatible install" >&5 if test -z "$INSTALL"; then if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -2179,7 +2183,7 @@ esac # Extract the first word of "rsync", so it can be a program name with args. set dummy rsync; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2183: checking for $ac_word" >&5 +echo "configure:2187: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_RSYNC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2651,6 +2655,8 @@ s%@DELAYTHRESH@%$DELAYTHRESH%g s%@PELABSUPPORT@%$PELABSUPPORT%g s%@TBOPSEMAIL@%$TBOPSEMAIL%g s%@TBOPSEMAIL_NOSLASH@%$TBOPSEMAIL_NOSLASH%g +s%@TBROBOCOPSEMAIL@%$TBROBOCOPSEMAIL%g +s%@TBROBOCOPSEMAIL_NOSLASH@%$TBROBOCOPSEMAIL_NOSLASH%g s%@TBLOGSEMAIL@%$TBLOGSEMAIL%g s%@TBLOGSEMAIL_NOSLASH@%$TBLOGSEMAIL_NOSLASH%g s%@TBWWWEMAIL@%$TBWWWEMAIL%g diff --git a/configure.in b/configure.in index bb4f343733..c1d53dfdf4 100755 --- a/configure.in +++ b/configure.in @@ -162,6 +162,8 @@ AC_SUBST(PELABSUPPORT) # AC_SUBST(TBOPSEMAIL) AC_SUBST(TBOPSEMAIL_NOSLASH) +AC_SUBST(TBROBOCOPSEMAIL) +AC_SUBST(TBROBOCOPSEMAIL_NOSLASH) AC_SUBST(TBLOGSEMAIL) AC_SUBST(TBLOGSEMAIL_NOSLASH) AC_SUBST(TBWWWEMAIL) @@ -314,6 +316,8 @@ fi # TBOPSEMAIL_NOSLASH="$TBOPSEMAIL" TBOPSEMAIL="`echo $TBOPSEMAIL | sed -e 's/@/\\\@/'`" +TBROBOCOPSEMAIL_NOSLASH="$TBROBOCOPSEMAIL" +TBROBOCOPSEMAIL="`echo $TBROBOCOPSEMAIL | sed -e 's/@/\\\@/'`" TBLOGSEMAIL_NOSLASH="$TBLOGSEMAIL" TBLOGSEMAIL="`echo $TBLOGSEMAIL | sed -e 's/@/\\\@/'`" TBAUDITEMAIL_NOSLASH="$TBAUDITEMAIL" diff --git a/db/libdb.pm.in b/db/libdb.pm.in index c85eaf3109..b5a1f4e897 100644 --- a/db/libdb.pm.in +++ b/db/libdb.pm.in @@ -223,6 +223,8 @@ use vars qw(@ISA @EXPORT); TBRobotLabExpt + TBExptContainsNodeCT + ); # Must come after package declaration! @@ -3301,6 +3303,33 @@ sub TBRobotLabExpt($$) return 1; } +# +# is a certain type/class node present? +# args: pid, eid, valid type/class +# +sub TBExptContainsNodeCT($$$) +{ + my ($pid,$eid,$ntc) = @_; + + # find out if this is a valid class or type... + my $dbq = DBQueryWarn("select v.pid,v.eid,v.type from virt_nodes as v " . + "left join node_types as nt on v.type=nt.type " . + "where v.pid='$pid' and v.eid='$eid' and " . + "(nt.class='$ntc' or nt.type='$ntc')"); + + +#"select r.pid,r.eid,r.node_id from reserved as r " . +#"left join nodes as n on n.node_id=r.node_id " . +#"left join node_types as nt on nt.type=n.type " . +#"where r.pid='$pid' and r.eid='$eid' and " . +#"(nt.class='$ntc' or nt.type='$ntc')"); + + return 0 + if (!$dbq || !$dbq->numrows()); + + return 1; +} + # # List of tables used for experiment removal/backup/restore. # diff --git a/defs-default b/defs-default index 152b62b071..a1d4eb3015 100644 --- a/defs-default +++ b/defs-default @@ -9,6 +9,7 @@ TBDBNAME=tbdb TBADMINGROUP=flux TBOPSEMAIL=testbed-ops@flux.utah.edu TBLOGSEMAIL=testbed-logs@flux.utah.edu +TBROBOCOPSEMAIL=testbed-robocops@flux.utah.edu TBWWWEMAIL=testbed-www@flux.utah.edu TBAPPROVALEMAIL=testbed-approval@flux.utah.edu TBAUDITEMAIL=testbed-audit@flux.utah.edu diff --git a/defs-johnsond-emulab b/defs-johnsond-emulab index fc01be3dfa..cfa8b4f870 100644 --- a/defs-johnsond-emulab +++ b/defs-johnsond-emulab @@ -4,6 +4,7 @@ . defs-default TBOPSEMAIL=johnsond@flux.utah.edu +TBROBOCOPSEMAIL=johnsond@cs.utah.edu TBLOGSEMAIL=johnsond@flux.utah.edu TBWWWEMAIL=johnsond@flux.utah.edu TBAPPROVALEMAIL=johnsond@flux.utah.edu diff --git a/tbsetup/power_mail.pm.in b/tbsetup/power_mail.pm.in index 20acbe3665..2b1b5fd81b 100644 --- a/tbsetup/power_mail.pm.in +++ b/tbsetup/power_mail.pm.in @@ -108,9 +108,11 @@ sub mailctrl($@) { } $cond_str .= " node_id='$node'"; } - $cond_str .= ") group by email"; + $cond_str .= ")"; - my $dbres = DBQueryFatal("select email from location_info ".$cond_str); + my $dbres = DBQueryFatal("select email from location_info " . + $cond_str . " group by email"); + if ($dbres->num_rows() != 0) { my $row; while (($row = $dbres->fetchrow_hashref())) { @@ -124,19 +126,70 @@ sub mailctrl($@) { push @emails, $TBOPS; } + my $email_body = + "Someone needs to power $cmd the following nodes:\n" . + "\t\n" . join(" ",@nodes) . "\n\nfor $pid/$eid, " . + "swapped in by $swapper_uid.\n" . + "\nAnd update power time through this web page:\n" . + "\n https://$WWW/powertime.php3?node_id=" . join(",",@nodes) . + "\n"; + + $dbres = DBQueryFatal("select node_id,battery_voltage as v, " . + "battery_percentage as p, " . + "(UNIX_TIMESTAMP(NOW()) - battery_timestamp)". + " as tdelta from nodes " . + "where battery_voltage is not NULL"); + my $row; + my %powinfo = (); + while (($row = $dbres->fetchrow_hashref())) { + $powinfo{$row->{'node_id'}} = { 'v' => $row->{'v'}, + 'p' => $row->{'p'}, + 'tdelta' => $row->{'tdelta'} + }; + } + + $email_body .= + "\nHere's the last known battery info for these robots. If \n" . + "it's been more than 3 days since last power update, or if \n" . + "the remaining percent is below 50 or the voltage is below 7.5,\n". + "you should probably replace the battery.\n\n"; + + foreach $bot (@nodes) { + if (defined($powinfo{$bot})) { + my $ts = $powinfo{$bot}{'tdelta'}; + my $time_str; + if ($ts > (3600*24)) { + my $tts = sprintf("%.2f",($ts / (3600*24))); + $time_str = $tts . " days since last update."; + } + else { + my $tts = sprintf("%.2f",($ts / 3600)); + $time_str = $tts . " hours since last update."; + } + + $email_body .= + $bot . ": " . sprintf("%.2f",$powinfo{$bot}{'p'}) . + "%, " . sprintf("%.2f",$powinfo{$bot}{'v'}) . + "V, " . $time_str . "\n"; + } + else { + $email_body .= "$bot: no info!!!\n"; + } + } + + $email_body .= "\nThe Power Control Dude.\n"; + foreach $email (@emails) { + #print "Sending to $email\n\n"; if ($email ne "") { SENDMAIL($email, - "Power $cmd nodes for $pid/$eid\n" . - "Someone needs to power $cmd the following nodes:\n" . - "\t\n" . join(" ",@nodes) . "\n\nfor $pid/$eid, " . - "swapped in by $swapper_uid.\n" . - "\nAnd update power time through this web page:\n" . - "\n https://$WWW/powertime.php3?node_id=" . join(",",@nodes), - $TBOPS); + "Power $cmd nodes for $pid/$eid\n", + $email_body); } } + + foreach my $node (keys %actual) { my $tries = $default_tries; my $ok = 0; diff --git a/tbsetup/swapexp.in b/tbsetup/swapexp.in index f0217ba948..70da8f241c 100644 --- a/tbsetup/swapexp.in +++ b/tbsetup/swapexp.in @@ -65,6 +65,7 @@ sub ExitWithStatus($$) # my $TB = "@prefix@"; my $TBOPS = "@TBOPSEMAIL@"; +my $TBROBOCOPS = "@TBROBOCOPSEMAIL@"; my $TBLOGS = "@TBLOGSEMAIL@"; my $TBINFO = "$TB/expinfo"; my $TBDOCBASE = "@TBDOCBASE@"; @@ -102,6 +103,7 @@ my $eventsys_restart = 0; my $errorstat= -1; my $modifyHosed = 0; my $modifySwapped = 0; +my $robotexp = 0; my $inout; my $logname; @@ -321,6 +323,16 @@ if ($overquota) { # my $firewalled = TBExptFirewall($pid, $eid); +# +# see if we've got a robot exp (this isn't the only check; if this is a +# swapmod, we've got to check tbprerun as well... +# +$robotexp = + TBExptContainsNodeCT($pid,$eid,'robot') || + TBExptContainsNodeCT($pid,$eid,'mote') || + TBExptContainsNodeCT($pid,$eid,'motehost') || + TBExptContainsNodeCT($pid,$eid,'powermon'); + # # We have to protect against trying to end an experiment that is currently # in the process of being terminated. We use a "wrapper" state (actually @@ -1291,6 +1303,15 @@ sub cleanup() # # Send a message to the testbed list. Append the logfile. # + + # + # also try to send mail to robocops if it was a robot/mote exp + # + my $rcops = ''; + if ($robotexp) { + $rcops = "\nCc: $TBROBOCOPS"; + } + SENDMAIL("$user_name <$user_email>", "Swap ${inout} Failure: $pid/$eid", "Please look at the log below to see what happened. If the error\n". @@ -1305,7 +1326,7 @@ sub cleanup() "#BatchMode\n", ($idleswap ? $TBOPS : "$user_name <$user_email>"), "Cc: $expt_head_name <$expt_head_email>\n". - "Cc: $TBOPS", + "Cc: $TBOPS $rcops", (($logname), (defined($modnsfile) ? ($modnsfile) : ()))); if ($modifyHosed) { -- GitLab