-import re, time, sha
+import re, time, sha, os.path
from base64 import b32decode
from zope.interface import implements
from twisted.application import service
def __init__(self, basedir="."):
node.Node.__init__(self, basedir)
self.init_introducer()
+ webport = self.get_config("webport")
+ if webport:
+ self.init_web(webport) # strports string
def init_introducer(self):
introducerservice = IntroducerService(self.basedir)
d.addCallback(_publish)
d.addErrback(log.err, facility="tahoe.init", level=log.BAD)
+ def init_web(self, webport):
+ self.log("init_web(webport=%s)", args=(webport,))
+
+ from allmydata.webish import IntroducerWebishServer
+ nodeurl_path = os.path.join(self.basedir, "node.url")
+ ws = IntroducerWebishServer(webport, nodeurl_path)
+ self.add_service(ws)
+
class IntroducerService(service.MultiService, Referenceable):
implements(RIIntroducerPublisherAndSubscriberService)
name = "introducer"
kwargs["facility"] = "tahoe.introducer"
return log.msg(*args, **kwargs)
+ def get_announcements(self):
+ return frozenset(self._announcements)
+ def get_subscribers(self):
+ return self._subscribers
+
def remote_publish(self, announcement):
self.log("introducer: announcement published: %s" % (announcement,) )
(furl, service_name, ri_name, nickname, ver, oldest) = announcement
from twisted.internet import threads # CLI tests use deferToThread
from twisted.internet.error import ConnectionDone, ConnectionLost
from twisted.application import service
+import allmydata
from allmydata import client, uri, download, upload, storage, mutable, offloaded
from allmydata.introducer import IntroducerNode
from allmydata.util import deferredutil, fileutil, idlib, mathutil, testutil
iv_dir = self.getdir("introducer")
if not os.path.isdir(iv_dir):
fileutil.make_dirs(iv_dir)
+ f = open(os.path.join(iv_dir, "webport"), "w")
+ f.write("tcp:0:interface=127.0.0.1\n")
+ f.close()
iv = IntroducerNode(basedir=iv_dir)
self.introducer = self.add_service(iv)
d = self.introducer.when_tub_ready()
+ d.addCallback(self._get_introducer_web)
d.addCallback(self._set_up_stats_gatherer)
d.addCallback(self._set_up_nodes_2)
d.addCallback(self._grab_stats)
return d
+ def _get_introducer_web(self, res):
+ f = open(os.path.join(self.getdir("introducer"), "node.url"), "r")
+ self.introweb_url = f.read().strip()
+ f.close()
+
def _set_up_stats_gatherer(self, res):
statsdir = self.getdir("stats_gatherer")
fileutil.make_dirs(statsdir)
permuted_peers = list(c.get_permuted_peers("storage", "a"))
self.failUnlessEqual(len(permuted_peers), self.numclients)
d.addCallback(_check_connections)
+
def _do_upload(res):
log.msg("UPLOADING")
u = self.clients[0].getServiceNamed("uploader")
self.basedir = "system/SystemTest/test_vdrive"
self.data = LARGE_DATA
d = self.set_up_nodes(createprivdir=True)
+ d.addCallback(self._test_introweb)
d.addCallback(self.log, "starting publish")
d.addCallback(self._do_publish1)
d.addCallback(self._test_runner)
return d
test_vdrive.timeout = 1100
+ def _test_introweb(self, res):
+ d = getPage(self.introweb_url, method="GET", followRedirect=True)
+ def _check(res):
+ try:
+ self.failUnless("allmydata: %s" % str(allmydata.__version__)
+ in res)
+ self.failUnless("Clients:" in res)
+ except unittest.FailTest:
+ print
+ print "GET %s output was:" % self.introweb_url
+ print res
+ raise
+ d.addCallback(_check)
+ return d
+
def _do_publish1(self, res):
ut = upload.Data(self.data)
c0 = self.clients[0]
--- /dev/null
+
+from nevow import rend
+from foolscap.referenceable import SturdyRef
+from twisted.internet import address
+import allmydata
+from allmydata import get_package_versions_string
+from allmydata.util import idlib
+from common import getxmlfile, IClient
+
+class IntroducerRoot(rend.Page):
+
+ addSlash = True
+ docFactory = getxmlfile("introducer.xhtml")
+
+ def data_version(self, ctx, data):
+ return get_package_versions_string()
+ def data_import_path(self, ctx, data):
+ return str(allmydata)
+ def data_my_nodeid(self, ctx, data):
+ return idlib.nodeid_b2a(IClient(ctx).nodeid)
+
+ def data_known_storage_servers(self, ctx, data):
+ i = IClient(ctx).getServiceNamed("introducer")
+ storage = [1
+ for (furl, service_name, ri_name, nickname, ver, oldest)
+ in i.get_announcements()
+ if service_name == "storage"]
+ return len(storage)
+
+ def data_num_clients(self, ctx, data):
+ i = IClient(ctx).getServiceNamed("introducer")
+ num_clients = 0
+ subscribers = i.get_subscribers()
+ for service_name,who in subscribers.items():
+ num_clients += len(who)
+ return num_clients
+
+ def data_services(self, ctx, data):
+ i = IClient(ctx).getServiceNamed("introducer")
+ ann = list(i.get_announcements())
+ ann.sort(lambda a,b: cmp( (a[1], a), (b[1], b) ) )
+ return ann
+
+ def render_service_row(self, ctx, announcement):
+ (furl, service_name, ri_name, nickname, ver, oldest) = announcement
+ sr = SturdyRef(furl)
+ nodeid = sr.tubID
+ advertised = [loc.split(":")[0] for loc in sr.locationHints]
+ ctx.fillSlots("peerid", "%s %s" % (idlib.nodeid_b2a(nodeid), nickname))
+ ctx.fillSlots("advertised", " ".join(advertised))
+ ctx.fillSlots("connected", "?")
+ ctx.fillSlots("since", "?")
+ ctx.fillSlots("announced", "?")
+ ctx.fillSlots("version", ver)
+ ctx.fillSlots("service_name", service_name)
+ return ctx.tag
+
+ def data_subscribers(self, ctx, data):
+ i = IClient(ctx).getServiceNamed("introducer")
+ s = []
+ for service_name, subscribers in i.get_subscribers().items():
+ for rref in subscribers:
+ s.append( (service_name, rref) )
+ s.sort()
+ return s
+
+ def render_subscriber_row(self, ctx, s):
+ (service_name, rref) = s
+ sr = rref.getSturdyRef()
+ nodeid = sr.tubID
+ ctx.fillSlots("peerid", "%s" % idlib.nodeid_b2a(nodeid))
+ advertised = [loc.split(":")[0] for loc in sr.locationHints]
+ ctx.fillSlots("advertised", " ".join(advertised))
+ remote_host = rref.tracker.broker.transport.getPeer()
+ if isinstance(remote_host, address.IPv4Address):
+ remote_host_s = "%s:%d" % (remote_host.host, remote_host.port)
+ else:
+ # loopback is a non-IPv4Address
+ remote_host_s = str(remote_host)
+ ctx.fillSlots("connected", remote_host_s)
+ ctx.fillSlots("since", "?")
+ ctx.fillSlots("service_name", service_name)
+ return ctx.tag
+
+
from nevow.util import resource_filename
-from allmydata.web import status, unlinked
+from allmydata.web import status, unlinked, introweb
from allmydata.web.common import IClient, getxmlfile, get_arg, \
boolean_of_arg, abbreviate_size
class WebishServer(service.MultiService):
name = "webish"
+ root_class = Root
def __init__(self, webport, nodeurl_path=None):
service.MultiService.__init__(self)
self.webport = webport
- self.root = Root()
+ self.root = self.root_class()
self.site = site = appserver.NevowSite(self.root)
self.site.requestFactory = MyRequest
self.allow_local = LocalAccess()
f.write(base_url + "\n")
f.close()
+class IntroducerWebishServer(WebishServer):
+ root_class = introweb.IntroducerRoot