From 9323263d694cde2e64a01ad691860dc791181ef4 Mon Sep 17 00:00:00 2001 From: Robert Ricci <ricci@cs.utah.edu> Date: Wed, 15 Dec 2004 22:33:46 +0000 Subject: [PATCH] Blinky light support for motes on stargates. Display a new 'Blinky Lights' button on the showexp page. In order to do this, I have to get a list of which classes/types are in use in the experiment. This leads to moteleds.php3, which displays the blink lights using Tim's cool Java applet. --- configure | 2 +- utils/GNUmakefile.in | 2 +- utils/spewleds.in | 79 ++++++++++++++++++++++++++++++++++++++ www/BlinkenLichten.class | Bin 2414 -> 2744 bytes www/BlinkenLichten.java | 37 +++++++++++++----- www/ledpipe.php3 | 54 ++++++++++++++++++++------ www/moteleds.php3 | 80 +++++++++++++++++++++++++++++++++++++++ www/showexp.php3 | 21 ++++++++++ www/showstuff.php3 | 2 +- 9 files changed, 254 insertions(+), 23 deletions(-) create mode 100755 utils/spewleds.in create mode 100644 www/moteleds.php3 diff --git a/configure b/configure index 4a9fedec0e..d4a4436e80 100755 --- a/configure +++ b/configure @@ -1559,7 +1559,7 @@ outfiles="$outfiles Makeconf GNUmakefile \ utils/cvsupd.pl utils/newnode utils/grantnodetype \ utils/nsgen/GNUmakefile utils/nsgen/webnsgen \ utils/link_config utils/import_commitlog utils/dhcpd_wrapper \ - utils/opsreboot utils/deletenode utils/webdeletenode \ + utils/opsreboot utils/deletenode utils/webdeletenode utils/spewleds \ www/GNUmakefile www/defs.php3 www/dbdefs.php3 \ www/swish.conf www/websearch \ vis/GNUmakefile vis/webvistopology vis/dbvistopology \ diff --git a/utils/GNUmakefile.in b/utils/GNUmakefile.in index bd0e935396..054396dc88 100644 --- a/utils/GNUmakefile.in +++ b/utils/GNUmakefile.in @@ -18,7 +18,7 @@ BIN_SCRIPTS = delay_config sshtb create_image node_admin link_config SBIN_SCRIPTS = vlandiff vlansync withadminprivs export_tables cvsupd.pl \ eventping grantnodetype import_commitlog dhcpd_wrapper \ opsreboot deletenode node_statewait -LIBEXEC_SCRIPTS = webcreateimage newnode webdeletenode +LIBEXEC_SCRIPTS = webcreateimage newnode webdeletenode spewleds # # Force dependencies on the scripts so that they will be rerun through diff --git a/utils/spewleds.in b/utils/spewleds.in new file mode 100755 index 0000000000..c08cf18e38 --- /dev/null +++ b/utils/spewleds.in @@ -0,0 +1,79 @@ +#!/usr/bin/perl -wT + +# +# EMULAB-COPYRIGHT +# Copyright (c) 2004 University of Utah and the Flux Group. +# All rights reserved. +# + +# +# Simple script to connect to the LED status port on a stargate and spew the LED status +# to stdout +# + +use English; +use Getopt::Std; +use IO::Socket; + +use lib '@prefix@/lib'; +use libdb; + +my $LED_STATUS_PORT = 1812; + +# Make output unbuffered +$| = 1; + +# +# Args +# +if (@ARGV != 1) { + die "Usage: spewleds mote\n"; +} + +my ($mote) = @ARGV; + +# +# Untaint the argument. +# +if ($mote =~ /^([-\w.]+)$/) { + $mote = $1; +} else { + die("Tainted node name: $mote"); +} + +# +# Make sure they have permissions to see this node +# +if (! TBNodeAccessCheck($UID, TB_NODEACCESS_READINFO, $mote)) { + print STDERR + "*** osload: Not enough permission to view that node!\n"; + exit 1; +} + +# +# Make sure it's a stargate or garcia (XXX garcia should be temporary) +# +my ($type, $class) = TBNodeType($mote); +if ($type ne "garcia" && $class ne "sg") { + die "Node $mote is not of the correct type ($type,$class)\n"; +} + +# +# Connect to the LED status port +# +my $sock = new IO::Socket::INET ( + PeerAddr => "$mote", + PeerPort => "$LED_STATUS_PORT", + Proto => 'tcp', + ); +die "Could not create socket: $!\n" unless $sock; + +# +# Okie, just loop on this guy forever +# +while (my $string = <$sock>) { + print "$string" +} + +close $sock; +exit 0; diff --git a/www/BlinkenLichten.class b/www/BlinkenLichten.class index 3e6b3fb2c59e0fe162a19145fae62db8317dcb69..265cbe65d9a70cee43c4783c859d4475deaf7770 100644 GIT binary patch delta 1502 zcmY+EYgbfd6vuyunK@@T9d#Tc9Sc**gfkL&i2@1`@`4R`Nl~Ogj0rDXlDuRVW0r|p zMowmCrd{b?2o9`h`JxxS=qvOMdeKLy{tpAOTr+3y{p|hUd+pov{2iUhPyO-FFLww~ z!tF3^VcNr-3iD~0pB!Ft7;<>e;gUnz;eCh84j(vNarn^Ts>4SP*Bm}}xbE<Yi$kT$ ze5za`JmHeZlSZn}B}|RW9BN%j>s<1wbGe6l<B@vG<zChsaf3@P8x49>E;bFhxNJ7k z(<WBJmDK1GrOCwFVsKlHb(?Y9Zpbqx>JAfcr#UtoX_v`px5=Z$WgdG>&{pI7tnq!$ zOVQ5@p2#6XdJXCGNYUf*I<I(~Hr6-T>v4u|kGJUZI7_F;Ap1Pd8Qpn0JT4gU+YETT z!^<A;a?;}lNspTx@c7I``JBTZUl`n%2KSZGeZ7|b9^V-9EiZa}XQc0q^n)?~$nzc} z9Q3$lqK+EpF$U5pt1vHGRGc{2ajc`X<M@%%`o8YI{;JWN)-}s^idyR$8qzg^KOMWX zqyJE{KfN%xdw!^^Kbh>c2v70$zTVN^;1(<WTd2;l`;(ngq;u>GDGU2Vvb($QxJ7PO zkcFjcmV?Dyg5;R$KwNc9an(J=m72IMoSG_nRHp)QOFZO{bKi&rixblzDAwuX3{)ta zlq2Jye~bGwl!~p)u-ebCB;iLx8J0Eq(STTG(2oWU4^5KS5}zc}5(`aGKF-2uPKHG# z6D$^sS|YJv_K@Mxabk@MSX61pY`L$B*$TGCkJ%ZP-e$!l^IK9%b3ul+BZ+the?<As z)gqkM+GX=@V}TMZRWr(DS*>rama~FIRI-dJe5z%wkyNYSIyO>Af_ipI-^zMA*g%)G zJ#69_n-zPtq9?RsP1>sx)c@g`hG-jtx|+}$v40IGhN<-9fi;m;H*f;O1cSFJ@#CSp z6wCd%bC;q*&3nWjV?{g=QJL}U|K1rUY`Wn4mTEQ?hG=9f-c*GtDA)CZ9a1;zYt>z8 zBSyPQ+pDtnskl}-G|MH)HWjmzgY03u+<)ePsG0gQZAXr{?W>K&vtxIsw0(-(Bc$%e zH2yDXLc*U<Dc{1zm18_+cUOx&Tpm>RC0CgfpIU~pVIo<nAcOv8@j##;U&DM*u;p3U zLsDm9l4f89v#^RR?D79$l4fA3g3$hH<ZRYW8ZjJEhDX(=V_Jrj>d31s5iiuvm+8T% z&?sv)%8lZic~b*Fqkf%Le+KClKdg6RK+nWE-3?3jnfuYGlj&5x8Pe}GL=4aH!0ZB| kC7U-r9$2i^gCTvFB&B5=lJ&A4xGQ?@E-Kn<vgL5(KP$5h00000 delta 1173 zcmYL|%Xbt-6vlr&-7__53kZXO3=)I@CiY}PcnO3zgoikTh)4{H!6>45NbqP-6k}sR z2@1Z(S5(C3$vOg^9OH56!o4e(uH5)1s9z<4oIZ6Qb#Hz3-FvIYYyQc_zyJI5ulN-C zG0WjBk7YTN<>M^h8lE!@8ZH<v8s0LzZMb9@GF&#iV|dqa#c<W|p5cAN2O)-aA#-^k zq?+|1^Vs05ja6i64VlHJkQz3J+{G4`yfx%*;%&~{9#X}QDnfQvkztn;Z4O~~C~Hqh zj=c_HpTm04CGU6QA%|6RFlFZ+aMr_)!a;ZOBO!A*<Uk*_JWHn&Pdf3m6UQz6JY{2E z=CtJ%7k-r<%WHI5&e36cop#HB+k1l}mY814o4jE8ke4hUanw?w+wzG!`za?ZpE;<{ zo%;n(SiW@PE1t1jbJo|+y6&Ri@VMoBj#++4(OVhymfiT<8}@>9W9QDwkpE}pRB+_R zA3@pkQ>XhXOEPVh-pu8grRs&jV>T&$q5{%lBc0K{YLt9lUY)cjosPzsKPtncZ#oGY z<ek5rsw@WzL(xy%lh7m;C9KrCw-n{l2}=(|IbSMn4We8iqcuIjypF;I)gAftIBUkJ z&7~3+7RRZR%6Ss`V9H5YJx0FVlyF~bCZEyq=6ptIEm1y`u;doYCz#tImJ1SAjg|@t zjiaJBTh$F}=u@=2Ss;ROQ9PR!YSCJ)x3QjuY@nWvL~LdyTiC=_wzG}Bk|lP~uKiAS z(L<Y>vzuP_Xx#e*-Xi$@Tu{~}3c6<ac0V+5UmvUse#w?bsErE#n(9^8F|j{F5Zq#g zT2qK_vRq{EzxLl>BV=8DjghBn9Qi;Uj<D0@oApHDkaiDiwX24s)Y8Qw*$vu@I3@-? z;(wgA9Mq}r=$3S2te+gTCKTzexM60Hp#pG{w94|_E1W*ir5#7UNgV6TBDrFiS%t}o z7DotWX~e~X?>F6Kt=6)H#WSdjCm%weF#1LRj9T2!eEk}AoE60rr*z5LJAEq4b0lh9 tD}JNesf0x{Gel#WbEgec*aJEc>z4D14JbOO-}It>+H(SXQLz*!{|91xx>*1K diff --git a/www/BlinkenLichten.java b/www/BlinkenLichten.java index 85237de751..0a40a5c4ca 100644 --- a/www/BlinkenLichten.java +++ b/www/BlinkenLichten.java @@ -34,7 +34,9 @@ public class BlinkenLichten /** * The current status of the light, just on/off for now. */ - private boolean on; + private boolean red_on; + private boolean green_on; + private boolean yellow_on; public BlinkenLichten() { @@ -79,15 +81,19 @@ public class BlinkenLichten public void run() { - byte buffer[] = new byte[1]; + byte buffer[] = new byte[6]; try { /* Just read a character at a time from the other side. */ - while( this.is.read(buffer) > 0 ) + // Bad, bad, bad + //while( this.is.read(buffer) > 0 ) + while( this.is.read(buffer,0,6) > 0 ) { /* 1 == on, 0 == off */ - this.on = (buffer[0] == '1'); + this.red_on = (buffer[0] == '1'); + this.green_on = (buffer[2] == '1'); + this.yellow_on = (buffer[4] == '1'); repaint(); } @@ -108,16 +114,29 @@ public class BlinkenLichten public void paint(Graphics g) { Dimension size = getSize(); + int width = size.width / 3; + int height = size.height; /* - * Just paint the entire canvas provided to the applet, no need to get - * fancy. + * Paint each of the three LED values */ - if( this.on ) + if (this.red_on) g.setColor(Color.red); else - g.setColor(Color.black); - g.fillRect(0, 0, size.width, size.height); + g.setColor(Color.red.darker().darker()); + g.fillRect(0, 0, width, height); + + if (this.green_on) + g.setColor(Color.green); + else + g.setColor(Color.green.darker().darker()); + g.fillRect(width, 0, width, height); + + if (this.yellow_on) + g.setColor(Color.yellow); + else + g.setColor(Color.yellow.darker().darker()); + g.fillRect(width *2, 0, width, height); } public void destroy() diff --git a/www/ledpipe.php3 b/www/ledpipe.php3 index 675d18a6f5..166efb7566 100644 --- a/www/ledpipe.php3 +++ b/www/ledpipe.php3 @@ -7,12 +7,7 @@ include("defs.php3"); # -# Standard Testbed Header -# -#PAGEHEADER("Watch Experiment Log"); - -# -# Only known and logged in users can end experiments. +# Only known and logged in users can watch LEDs # $uid = GETLOGIN(); LOGGEDINORDIE($uid); @@ -42,11 +37,48 @@ header("Cache-Control: no-cache, must-revalidate"); header("Pragma: no-cache"); flush(); -for ($lpc = 0; $lpc < 30; $lpc++) { - sleep(1); - $on_off = $lpc % 2; - echo "$on_off"; - flush(); +#for ($lpc = 0; $lpc < 30; $lpc++) { + # sleep(1); + # $on_off = $lpc % 2; + # echo "$on_off"; + # flush(); + #} + +# +# Silly, I can't get php to get the buffering behavior I want with a socket, so +# we'll open a pipe to a perl process +# +$socket = popen("$TBSUEXEC_PATH $uid nobody spewleds $node","r"); +if (!$socket) { + USERERROR("Error opening $node - $errstr",1); +} + +# +# Clean up when the remote user disconnects +# +function SPEWCLEANUP() +{ + global $socket; + + if (!$socket || !connection_aborted()) { + exit(); + } + pclose($socket); + exit(); +} +ignore_user_abort(1); +register_shutdown_function("SPEWCLEANUP"); + +# +# Just loop forver reading from the socket +# +while(!feof($socket)) { + + # Bad rob! No biscuit! + $onoff = fread($socket,6); + echo "$onoff"; + flush(); } +fclose($socket); ?> diff --git a/www/moteleds.php3 b/www/moteleds.php3 new file mode 100644 index 0000000000..c975ef5958 --- /dev/null +++ b/www/moteleds.php3 @@ -0,0 +1,80 @@ +<?php +# +# EMULAB-COPYRIGHT +# Copyright (c) 2004 University of Utah and the Flux Group. +# All rights reserved. +# + +include("defs.php3"); +include("showstuff.php3"); + +# +# Make sure they are logged in +# +$uid = GETLOGIN(); +LOGGEDINORDIE($uid); + +# +# Verify page arguments. +# +if (!isset($pid) || + strcmp($pid, "") == 0) { + USERERROR("You must provide a Project ID.", 1); +} + +if (!isset($eid) || + strcmp($eid, "") == 0) { + USERERROR("You must provide an Experiment ID.", 1); +} + +# +# Standard Testbed Header now that we have the pid/eid okay. +# +PAGEHEADER("View mote LEDs ($pid/$eid)"); + +# +# Make sure they have permission to view this experiment +# +if (! TBExptAccessCheck($uid, $pid, $eid, $TB_EXPT_READINFO)) { + USERERROR("You do not have permission to view experiment $exp_eid!", 1); +} + +# +# Get a list of all nodes in this experiment of type 'garcia' or 'stargate' +# +$query_result = + DBQueryFatal("select r.node_id,t.type,t.class from reserved as r ". + "left join nodes as n on ". + " r.node_id=n.node_id ". + "left join node_types as t on ". + " n.type=t.type ". + "where r.pid='$pid' and r.eid='$eid'"); + +if (mysql_num_rows($query_result) == 0) { + echo "<h3>No nodes to display in this experiment!</h3>\n"; +} else { + echo "<center> + <h3>Blinky Lights</h3> + </center> + <table align=center cellpadding=2 border=1> + <tr><th>Node</th><th>LEDs</th>\n"; + while ($row = mysql_fetch_array($query_result)) { + if ($row['type'] != "garcia" && $row['class'] != "sg") { + # Only the LEDs, mam + continue; + } + echo "<tr><th>$row[node_id]</th><td>"; + SHOWBLINKENLICHTEN($uid, + $HTTP_COOKIE_VARS[$TBAUTHCOOKIE], + "ledpipe.php3?node=$row[node_id]"); + } + echo "</table>\n"; + +} + +# +# Standard Testbed Footer +# +PAGEFOOTER(); + +?> diff --git a/www/showexp.php3 b/www/showexp.php3 index b3ddad5636..a0cdd5dd0c 100644 --- a/www/showexp.php3 +++ b/www/showexp.php3 @@ -72,6 +72,20 @@ $isbatch = $row["batchmode"]; $wireless = $row["wirelesslans"]; $linktest_running = $row["linktest_pid"]; +# +# Get a list of node types and classes in this experiment +# +$query_result = + DBQueryFatal("select distinct t.type,t.class from reserved as r " . + " left join nodes as n on r.node_id=n.node_id ". + " left join node_types as t on n.type=t.type ". + "where r.eid='$eid' and r.pid='$pid'"); +while ($row = mysql_fetch_array($query_result)) { + $classes[$row['class']] = 1; + $types[$row['type']] = 1; +} + + echo "<font size=+2>Experiment <b>". "<a href='showproject.php3?pid=$pid'>$pid</a>/". "<a href='showexp.php3?pid=$pid&eid=$eid'>$eid</a></b></font>\n"; @@ -194,6 +208,13 @@ if ($wireless) { WRITESUBMENUBUTTON("Show History", "showstats.php3?showby=expt&which=$expindex"); +# Blinky lights - but only if they have nodes of the correct type in their +# experiment +if ($types['garcia'] || $classes['sg']) { + WRITESUBMENUBUTTON("Show Blinky Lights", + "moteleds.php3?pid=$exp_pid&eid=$exp_eid"); +} + if (ISADMIN($uid)) { if ($expstate == $TB_EXPTSTATE_ACTIVE) { SUBMENUSECTION("Beta-Test Options"); diff --git a/www/showstuff.php3 b/www/showstuff.php3 index 7bceaa0a70..ee6ba4b4a5 100644 --- a/www/showstuff.php3 +++ b/www/showstuff.php3 @@ -1004,7 +1004,7 @@ function SHOWEXPLIST($type,$id,$gid = "") { # $HTTP_COOKIE_VARS[$TBAUTHCOOKIE], # "ledpipe.php3?node=em1"); # -function SHOWBLINKENLICHTEN($uid, $auth, $pipeurl, $width = 10, $height = 10) { +function SHOWBLINKENLICHTEN($uid, $auth, $pipeurl, $width = 30, $height = 10) { echo " <applet code='BlinkenLichten.class' width='$width' height='$height'> <param name='pipeurl' value='$pipeurl'> -- GitLab