Browse Source

Add a chutney "wait_until_bootstrap" command

It waits for up to 20 seconds, checking whether the logged
bootstrapped status for every node is 100%.  If it is, great: it
succeeds.  If not, it dumps the bootstrap statuses and exits.
Nick Mathewson 5 years ago
parent
commit
d4e4ee53e4
1 changed files with 56 additions and 0 deletions
  1. 56 0
      lib/chutney/TorNet.py

+ 56 - 0
lib/chutney/TorNet.py

@@ -787,6 +787,38 @@ class LocalNodeController(NodeController):
                     self._env['poll_launch_time_default']
             return False
 
+    def getLogfile(self, info=False):
+        """Return the expected path to the logfile for this instance."""
+        datadir = self._env['dir']
+        if info:
+            logname = "info.log"
+        else:
+            logname = "notice.log"
+        return os.path.join(datadir, logname)
+
+    def getLastBootstrapStatus(self):
+        """Look through the logs and return the last bootstrapp message
+           received as a 3-tuple of percentage complete, keyword
+           (optional), and message.
+        """
+        logfname = self.getLogfile()
+        if not os.path.exists(logfname):
+            return (-200, "no_logfile", "There is no logfile yet.")
+        percent,keyword,message=-100,"no_message","No bootstrap messages yet."
+        with open(logfname, 'r') as f:
+            for line in f:
+                m = re.search(r'Bootstrapped (\d+)% (\([^\)]*\))?: (.*)', line)
+                if m:
+                    percent, keyword, message = m.groups()
+                    percent = int(percent)
+        return (percent, keyword, message)
+
+    def isBootstrapped(self):
+        """Return true iff the logfile says that this instance is
+           bootstrapped."""
+        pct, _, _ = self.getLastBootstrapStatus()
+        return pct == 100
+
 # XXX: document these options
 DEFAULTS = {
     'authority': False,
@@ -1117,6 +1149,30 @@ class Network(object):
         print("Sending SIGHUP to nodes")
         return all([n.getController().hup() for n in self._nodes])
 
+    def wait_for_bootstrap(self):
+        print("Waiting for nodes to bootstrap...")
+        limit = 20 #bootstrap time
+        delay = 0.5
+        controllers = [n.getController() for n in self._nodes]
+        elapsed = 0.0
+        while elapsed < limit:
+            all_bootstrapped = True
+            for c in controllers:
+                if not c.isBootstrapped():
+                    all_bootstrapped = False
+                    break
+            if all_bootstrapped:
+                print("Everything bootstrapped after %s sec"%elapsed)
+                return True
+            time.sleep(delay)
+            elapsed += delay
+
+        print("Bootstrap failed. Node status:")
+        for c in controllers:
+            print(c.getLastBootstrapStatus())
+
+        return False
+
     def stop(self):
         controllers = [n.getController() for n in self._nodes]
         for sig, desc in [(signal.SIGINT, "SIGINT"),