source file: /home/buildslave/tahoe/edgy/build/src/allmydata/web/introweb.py
file stats: 127 lines, 123 executed: 96.9% covered
   1. 
   2. import time
   3. from nevow import rend, inevow
   4. from foolscap.referenceable import SturdyRef
   5. from twisted.internet import address
   6. import allmydata
   7. import simplejson
   8. from allmydata import get_package_versions_string
   9. from allmydata.util import idlib
  10. from common import getxmlfile, get_arg, IClient
  11. 
  12. class IntroducerRoot(rend.Page):
  13. 
  14.     addSlash = True
  15.     docFactory = getxmlfile("introducer.xhtml")
  16. 
  17.     def renderHTTP(self, ctx):
  18.         t = get_arg(inevow.IRequest(ctx), "t")
  19.         if t == "json":
  20.             return self.render_JSON(ctx)
  21.         return rend.Page.renderHTTP(self, ctx)
  22. 
  23.     def render_JSON(self, ctx):
  24.         i = IClient(ctx).getServiceNamed("introducer")
  25.         res = {}
  26.         clients = i.get_subscribers()
  27.         subscription_summary = dict([ (name, len(clients[name]))
  28.                                       for name in clients ])
  29.         res["subscription_summary"] = subscription_summary
  30. 
  31.         announcement_summary = {}
  32.         for (ann,when) in i.get_announcements().values():
  33.             (furl, service_name, ri_name, nickname, ver, oldest) = ann
  34.             if service_name not in announcement_summary:
  35.                 announcement_summary[service_name] = 0
  36.             announcement_summary[service_name] += 1
  37.         res["announcement_summary"] = announcement_summary
  38. 
  39.         return simplejson.dumps(res, indent=1)
  40. 
  41.     def data_version(self, ctx, data):
  42.         return get_package_versions_string()
  43.     def data_import_path(self, ctx, data):
  44.         return str(allmydata)
  45.     def data_my_nodeid(self, ctx, data):
  46.         return idlib.nodeid_b2a(IClient(ctx).nodeid)
  47. 
  48.     def render_announcement_summary(self, ctx, data):
  49.         i = IClient(ctx).getServiceNamed("introducer")
  50.         services = {}
  51.         for (ann,when) in i.get_announcements().values():
  52.             (furl, service_name, ri_name, nickname, ver, oldest) = ann
  53.             if service_name not in services:
  54.                 services[service_name] = 0
  55.             services[service_name] += 1
  56.         service_names = services.keys()
  57.         service_names.sort()
  58.         return ", ".join(["%s: %d" % (service_name, services[service_name])
  59.                           for service_name in service_names])
  60. 
  61.     def render_client_summary(self, ctx, data):
  62.         i = IClient(ctx).getServiceNamed("introducer")
  63.         clients = i.get_subscribers()
  64.         service_names = clients.keys()
  65.         service_names.sort()
  66.         return ", ".join(["%s: %d" % (service_name, len(clients[service_name]))
  67.                           for service_name in service_names])
  68. 
  69.     def data_services(self, ctx, data):
  70.         i = IClient(ctx).getServiceNamed("introducer")
  71.         ann = [(since,a)
  72.                for (a,since) in i.get_announcements().values()
  73.                if a[1] != "stub_client"]
  74.         ann.sort(lambda a,b: cmp( (a[1][1], a), (b[1][1], b) ) )
  75.         return ann
  76. 
  77.     def render_service_row(self, ctx, (since,announcement)):
  78.         (furl, service_name, ri_name, nickname, ver, oldest) = announcement
  79.         sr = SturdyRef(furl)
  80.         nodeid = sr.tubID
  81.         advertised = self.show_location_hints(sr)
  82.         ctx.fillSlots("peerid", "%s %s" % (nodeid, nickname))
  83.         ctx.fillSlots("advertised", " ".join(advertised))
  84.         ctx.fillSlots("connected", "?")
  85.         TIME_FORMAT = "%H:%M:%S %d-%b-%Y"
  86.         ctx.fillSlots("announced",
  87.                       time.strftime(TIME_FORMAT, time.localtime(since)))
  88.         ctx.fillSlots("version", ver)
  89.         ctx.fillSlots("service_name", service_name)
  90.         return ctx.tag
  91. 
  92.     def data_subscribers(self, ctx, data):
  93.         i = IClient(ctx).getServiceNamed("introducer")
  94.         # use the "stub_client" announcements to get information per nodeid
  95.         clients = {}
  96.         for (ann,when) in i.get_announcements().values():
  97.             if ann[1] != "stub_client":
  98.                 continue
  99.             (furl, service_name, ri_name, nickname, ver, oldest) = ann
 100.             sr = SturdyRef(furl)
 101.             nodeid = sr.tubID
 102.             clients[nodeid] = ann
 103. 
 104.         # then we actually provide information per subscriber
 105.         s = []
 106.         for service_name, subscribers in i.get_subscribers().items():
 107.             for (rref, timestamp) in subscribers.items():
 108.                 sr = rref.getSturdyRef()
 109.                 nodeid = sr.tubID
 110.                 ann = clients.get(nodeid)
 111.                 s.append( (service_name, rref, timestamp, ann) )
 112.         s.sort()
 113.         return s
 114. 
 115.     def render_subscriber_row(self, ctx, s):
 116.         (service_name, rref, since, ann) = s
 117.         nickname = "?"
 118.         version = "?"
 119.         if ann:
 120.             (furl, service_name_2, ri_name, nickname, version, oldest) = ann
 121. 
 122.         sr = rref.getSturdyRef()
 123.         # if the subscriber didn't do Tub.setLocation, nodeid will be None
 124.         nodeid = sr.tubID or "?"
 125.         ctx.fillSlots("peerid", "%s %s" % (nodeid, nickname))
 126.         advertised = self.show_location_hints(sr)
 127.         ctx.fillSlots("advertised", " ".join(advertised))
 128.         remote_host = rref.tracker.broker.transport.getPeer()
 129.         if isinstance(remote_host, address.IPv4Address):
 130.             remote_host_s = "%s:%d" % (remote_host.host, remote_host.port)
 131.         else:
 132.             # loopback is a non-IPv4Address
 133.             remote_host_s = str(remote_host)
 134.         ctx.fillSlots("connected", remote_host_s)
 135.         TIME_FORMAT = "%H:%M:%S %d-%b-%Y"
 136.         ctx.fillSlots("since",
 137.                       time.strftime(TIME_FORMAT, time.localtime(since)))
 138.         ctx.fillSlots("version", version)
 139.         ctx.fillSlots("service_name", service_name)
 140.         return ctx.tag
 141. 
 142.     def show_location_hints(self, sr, ignore_localhost=True):
 143.         advertised = []
 144.         for hint in sr.locationHints:
 145.             if isinstance(hint, str):
 146.                 # Foolscap-0.2.5 and earlier used strings in .locationHints
 147.                 if ignore_localhost and hint.startswith("127.0.0.1"):
 148.                     continue
 149.                 advertised.append(hint.split(":")[0])
 150.             else:
 151.                 # Foolscap-0.2.6 and later use tuples of ("ipv4", host, port)
 152.                 if hint[0] == "ipv4":
 153.                     host = hint[1]
 154.                 if ignore_localhost and host == "127.0.0.1":
 155.                     continue
 156.                 advertised.append(hint[1])
 157.         return advertised
 158. 
 159.