misc/boodlegrid.tac: tool to monitor a grid through its flogports

This commit is contained in:
Brian Warner 2008-03-26 16:09:34 -07:00
parent 5aa7986497
commit ccce37bb4a

142
misc/boodlegrid.tac Normal file
View File

@ -0,0 +1,142 @@
# -*- python -*-
"""Monitor a Tahoe grid, by playing sounds in response to remote events.
To install:
1: install Boodler, from http://www.eblong.com/zarf/boodler/
2: run "boodler.py -l listen.Sounds". This will run a daemon
that listens on a network socket (31863 by default) and
accepts commands in the form of "sound bird/crow1.aiff\n"
3: copy this file into a new directory, which we'll call $BASEDIR
4: write one or more logport FURLs into files named *.furl or *.furls, one
per line. All logports from all such files will be used.
5: launch this daemon with 'cd $BASEDIR && twistd -y boodlegrid.tac'
"""
import os, time
from zope.interface import implements
from twisted.application import service
from twisted.internet import protocol, reactor, defer
from foolscap import Tub, Referenceable
from foolscap.logging.interfaces import RILogObserver
from twisted.python import log
class Listener:
def __init__(self):
self.boodler = None # filled in when we connect to boodler
self.last = {}
def sound(self, name, slot=None, max=0.100):
if not self.boodler:
return
now = time.time()
if slot is None:
slot = name
if now < self.last.get(slot, 0) + max:
return # too soon
self.last[slot] = now
self.boodler.write("sound %s\n" % name)
def msg(self, m, furl):
#print "got it", m
message = m.get("message", m.get("format", ""))
# messages emitted by the Introducer: client join/leave
if message.startswith("introducer: subscription[storage] request"):
self.sound("voice/hooray.aiff")
if message.startswith("introducer: unsubscribing"):
self.sound("electro/zaptrill-fade.aiff")
# messages from the helper
if message == "file already found in grid":
print "already found"
self.sound("mech/ziplash-high.aiff")
#if message == "upload done":
if m.get("format") == "plaintext_hash=%(plaintext_hash)s, SI=%(SI)s, size=%(size)d":
size = m.get("size")
print "upload done, size", size
self.sound("mech/ziplash-low.aiff")
if "fetching " in message:
# helper grabbing ciphertext from client
self.sound("voice/phoneme/sh.aiff", max=0.5)
# messages from storage servers
if message.startswith("storage: slot_readv"):
#self.sound("voice/phoneme/r.aiff")
self.sound("percussion/wood-tap-hollow.aiff")
# messages from webapi
if message.startswith("Retrieve") and "starting" in message:
self.sound("mech/metal-clack.aiff")
if message.startswith("Publish") and "starting" in message:
#self.sound("mech/metal-clash.aiff")
self.sound("mech/clock-clang.aiff")
if "web" in message and "POST" in message and "t=set_children" in message:
self.sound("mech/door-slam.aiff")
# generic messages
#if m['level'] < 20:
# self.sound("mech/keyboard-1.aiff")
if m['level'] > 30: # SCARY or BAD
#self.sound("mech/alarm-bell.aiff")
self.sound("environ/thunder-tense.aiff")
print m, furl
elif m['level'] == 30: # WEIRD
self.sound("mech/glass-breaking.aiff")
print m, furl
elif m['level'] > 20: # UNUSUAL or INFREQUENT or CURIOUS
if "_check_for_done but we're not running" in message:
pass
else:
self.sound("mech/telephone-ring-old.aiff")
print m, furl
class BoodleSender(protocol.Protocol):
def connectionMade(self):
print "connected to boodler"
self.factory.listener.boodler = self.transport
class Bridge(Referenceable):
implements(RILogObserver)
def __init__(self, furl, listener):
self.furl = furl
self.listener = listener
def remote_msg(self, m):
d = defer.maybeDeferred(self.listener.msg, m, self.furl)
d.addErrback(log.err)
# never send errors to the remote side
class Monitor(service.MultiService):
def __init__(self):
service.MultiService.__init__(self)
self.tub = Tub()
self.tub.setServiceParent(self)
self.listener = Listener()
self.targets = []
for fn in os.listdir("."):
if fn.endswith(".furl") or fn.endswith(".furls"):
for i,line in enumerate(open(fn, "r").readlines()):
target = line.strip()
if target:
self.tub.connectTo(target, self._got_logpublisher,
fn, i, target)
cf = protocol.ClientFactory()
cf.listener = self.listener
cf.protocol = BoodleSender
reactor.connectTCP("localhost", 31863, cf)
def _got_logpublisher(self, publisher, fn, i, target):
print "connected to %s:%d, %s" % (fn, i, target)
b = Bridge(target, self.listener)
publisher.callRemote("subscribe_to_all", b)
m = Monitor()
application = service.Application("boodlegrid")
m.setServiceParent(application)