]> git.rkrishnan.org Git - tahoe-lafs/tahoe-lafs.git/blob - src/allmydata/node.py
control: add RIControlClient, fix some pyflakes warnings
[tahoe-lafs/tahoe-lafs.git] / src / allmydata / node.py
1
2 from twisted.application import service
3 import os.path
4 from foolscap import Tub
5 from allmydata.util.iputil import get_local_addresses
6 from allmydata.util import idlib
7 from twisted.python import log
8
9 class Node(service.MultiService):
10     # this implements common functionality of both Client nodes and the Queen
11     # node.
12     NODETYPE = "unknown NODETYPE"
13     PORTNUMFILE = None
14     CERTFILE = None
15     LOCAL_IP_FILE = "local_ip"
16     NODEIDFILE = "my_nodeid"
17
18     def __init__(self, basedir="."):
19         service.MultiService.__init__(self)
20         self.basedir = os.path.abspath(basedir)
21         assert self.CERTFILE, "Your node.Node subclass must provide CERTFILE"
22         certfile = os.path.join(self.basedir, self.CERTFILE)
23         if os.path.exists(certfile):
24             f = open(certfile, "rb")
25             self.tub = Tub(certData=f.read())
26             f.close()
27         else:
28             self.tub = Tub()
29             f = open(certfile, "wb")
30             f.write(self.tub.getCertData())
31             f.close()
32         self.nodeid = idlib.a2b(self.tub.tubID)
33         f = open(os.path.join(self.basedir, self.NODEIDFILE), "w")
34         f.write(idlib.b2a(self.nodeid) + "\n")
35         f.close()
36         self.short_nodeid = self.tub.tubID[:4] # ready for printing
37         portnum = 0
38         assert self.PORTNUMFILE, "Your node.Node subclass must provide PORTNUMFILE"
39         self._portnumfile = os.path.join(self.basedir, self.PORTNUMFILE)
40         if os.path.exists(self._portnumfile):
41             portnum = int(open(self._portnumfile, "r").read())
42         self.tub.listenOn("tcp:%d" % portnum)
43         # we must wait until our service has started before we can find out
44         # our IP address and thus do tub.setLocation, and we can't register
45         # any services with the Tub until after that point
46         self.tub.setServiceParent(self)
47
48         AUTHKEYSFILEBASE = "authorized_keys."
49         for f in os.listdir(self.basedir):
50             if f.startswith(AUTHKEYSFILEBASE):
51                 keyfile = os.path.join(self.basedir, f)
52                 portnum = int(f[len(AUTHKEYSFILEBASE):])
53                 from allmydata import manhole
54                 m = manhole.AuthorizedKeysManhole(portnum, keyfile)
55                 m.setServiceParent(self)
56                 self.log("AuthorizedKeysManhole listening on %d" % portnum)
57
58     def log(self, msg):
59         log.msg(self.short_nodeid + ": " + msg)
60
61     def _setup_tub(self, local_addresses):
62         # we can't get a dynamically-assigned portnum until our Tub is
63         # running, which means after startService.
64         l = self.tub.getListeners()[0]
65         portnum = l.getPortnum()
66         local_ip_filename = os.path.join(self.basedir, self.LOCAL_IP_FILE)
67         if os.path.exists(local_ip_filename):
68             f = open(local_ip_filename, "r")
69             local_ip = f.read()
70             f.close()
71             if local_ip not in local_addresses:
72                 local_addresses.append(local_ip)
73         if not os.path.exists(self._portnumfile):
74             # record which port we're listening on, so we can grab the same
75             # one next time
76             f = open(self._portnumfile, "w")
77             f.write("%d\n" % portnum)
78             f.close()
79         location = ",".join(["%s:%d" % (ip, portnum)
80                              for ip in local_addresses])
81         self.log("Tub location set to %s" % location)
82         self.tub.setLocation(location)
83         return self.tub
84
85     def tub_ready(self):
86         # called when the Tub is available for registerReference
87         pass
88
89     def add_service(self, s):
90         s.setServiceParent(self)
91         return s
92
93     def startService(self):
94         # note: this class can only be started and stopped once.
95         service.MultiService.startService(self)
96         local_addresses = get_local_addresses()
97         self._setup_tub(local_addresses)
98         self.tub_ready()
99         self.log("%s running" % self.NODETYPE)
100