From 7d692d0afdb63fd597145e04f335d7ac5fd7dda7 Mon Sep 17 00:00:00 2001 From: Brian Warner Date: Wed, 6 Jul 2016 19:47:00 -0700 Subject: [PATCH] Split control and log to two separate tubs, remove control knobs. This also removes the tahoe.cfg keys that would have configured the control-port. And it deletes the logport.furl file before asking the Tub to re-create it, because we're now using an ephemeral Tub (so we're not persisting the private key, so the tubid will change each time). closes ticket:2794 --- src/allmydata/node.py | 83 +++++++++++++++++++------------------------ topfiles/2794.change | 14 ++++++++ 2 files changed, 51 insertions(+), 46 deletions(-) create mode 100644 topfiles/2794.change diff --git a/src/allmydata/node.py b/src/allmydata/node.py index 7089d39bf..b7de9e930 100644 --- a/src/allmydata/node.py +++ b/src/allmydata/node.py @@ -85,6 +85,7 @@ class Node(service.MultiService): self.init_tempdir() self.create_tub() self.create_control_tub() + self.create_log_tub() self.logSource="Node" self.setup_logging() @@ -167,16 +168,6 @@ class Node(service.MultiService): return "tcp:%d" % int(s) return s - def get_control_tub_port(self): - # return a descriptor string - cfg_tubport = self.get_config("node", "control_tub.port", "") - if cfg_tubport: - return self._convert_tub_port(cfg_tubport) - - # XXX should really be: tcp:interface=127.0.0.1:1234 - tubport = "tcp:%d" % iputil.allocate_tcp_port() - return tubport - def get_tub_port(self): # return a descriptor string cfg_tubport = self.get_config("node", "tub.port", "") @@ -191,16 +182,6 @@ class Node(service.MultiService): fileutil.write_atomically(self._portnumfile, tubport + "\n", mode="") return tubport - def get_control_tub_location(self, tubport): - location = self.get_config("node", "control_tub.location", "127.0.0.1") - # Replace the location "AUTO", if present, with the detected local - # addresses. Don't probe for local addresses unless necessary. - split_location = location.split(",") - new_locations = [] - for loc in split_location: - new_locations.append(loc) - return ",".join(new_locations) - def get_tub_location(self, tubport): location = self.get_config("node", "tub.location", "AUTO") # Replace the location "AUTO", if present, with the detected local @@ -219,32 +200,13 @@ class Node(service.MultiService): new_locations.append(loc) return ",".join(new_locations) - def create_control_tub(self): - certfile = os.path.join(self.basedir, "private", self.CERTFILE) - self.control_tub = Tub(certFile=certfile) - self.control_tub_options = { - "logLocalFailures": True, - "logRemoteFailures": True, - "expose-remote-exception-types": False, - } - for (name, value) in self.control_tub_options.items(): - self.control_tub.setOption(name, value) - tubport = self.get_control_tub_port() - if tubport in ("0", "tcp:0"): - raise ValueError("tub.port cannot be 0: you must choose") - self.control_tub.listenOn(tubport) - - location = self.get_control_tub_location(tubport) - self.control_tub.setLocation(location) - self.log("Control/logging Tub location set to %s" % (location,)) - - # the Tub is now ready for tub.registerReference() - self.control_tub.setServiceParent(self) - def create_tub(self): certfile = os.path.join(self.basedir, "private", self.CERTFILE) self.tub = Tub(certFile=certfile) self.tub_options = { + "logLocalFailures": True, + "logRemoteFailures": True, + "expose-remote-exception-types": False, } # see #521 for a discussion of how to pick these timeout values. @@ -273,6 +235,33 @@ class Node(service.MultiService): # the Tub is now ready for tub.registerReference() self.tub.setServiceParent(self) + def create_control_tub(self): + # the control port uses a localhost-only ephemeral Tub, with no + # control over the listening port or location + self.control_tub = Tub() + portnum = iputil.allocate_tcp_port() + port = "tcp:%d:interface=127.0.0.1" % portnum + location = "tcp:127.0.0.1:%d" % portnum + self.control_tub.listenOn(port) + self.control_tub.setLocation(location) + self.log("Control Tub location set to %s" % (location,)) + self.control_tub.setServiceParent(self) + + def create_log_tub(self): + # The logport uses a localhost-only ephemeral Tub, with no control + # over the listening port or location. This might change if we + # discover a compelling reason for it in the future (e.g. being able + # to use "flogtool tail" against a remote server), but for now I + # think we can live without it. + self.log_tub = Tub() + portnum = iputil.allocate_tcp_port() + port = "tcp:%d:interface=127.0.0.1" % portnum + location = "tcp:127.0.0.1:%d" % portnum + self.log_tub.listenOn(port) + self.log_tub.setLocation(location) + self.log("Log Tub location set to %s" % (location,)) + self.log_tub.setServiceParent(self) + def get_app_versions(self): # TODO: merge this with allmydata.get_package_versions return dict(app_versions.versions) @@ -392,13 +381,15 @@ class Node(service.MultiService): # TODO: twisted >2.5.0 offers maxRotatedFiles=50 lgfurl_file = os.path.join(self.basedir, "private", "logport.furl").encode(get_filesystem_encoding()) - self.control_tub.setOption("logport-furlfile", lgfurl_file) + if os.path.exists(lgfurl_file): + os.remove(lgfurl_file) + self.log_tub.setOption("logport-furlfile", lgfurl_file) lgfurl = self.get_config("node", "log_gatherer.furl", "") if lgfurl: # this is in addition to the contents of log-gatherer-furlfile - self.control_tub.setOption("log-gatherer-furl", lgfurl) - self.control_tub.setOption("log-gatherer-furlfile", - os.path.join(self.basedir, "log_gatherer.furl")) + self.log_tub.setOption("log-gatherer-furl", lgfurl) + self.log_tub.setOption("log-gatherer-furlfile", + os.path.join(self.basedir, "log_gatherer.furl")) incident_dir = os.path.join(self.basedir, "logs", "incidents") foolscap.logging.log.setLogDir(incident_dir.encode(get_filesystem_encoding())) diff --git a/topfiles/2794.change b/topfiles/2794.change new file mode 100644 index 000000000..5eb69b77a --- /dev/null +++ b/topfiles/2794.change @@ -0,0 +1,14 @@ +The little-used "control port" now uses a separate (ephemeral) Tub. This +means the FURL changes each time the node is restarted, and it only listens +on the loopback (127.0.0.1) interface, on a random port. As the control port +is only used by some automated tests (check_memory, check_speed), this +shouldn't affect anyone. + +The slightly-more-used "log port" now also uses a separate (ephemeral) Tub, +with the same consequences. The lack of a stable (and externally-reachable) +logport.furl means it is no longer possible to use `flogtool tail FURL` +against a distant Tahoe server, however `flogtool tail +.../nodedir/private/logport.furl` still works just fine (and is the more +common use case anyways). We might bring back the ability to configure the +port and location of the logport in the future, if there is sufficient +demand, but for now it seems better to avoid the complexity.