# Having both pid and ppid makes it harder
# for pid rollover to induce tracking mistakes
self._started = False
+ self._setup = False
+ self._setuper = None
self._pid = None
self._ppid = None
def setup(self):
self._make_home()
self._build()
+ self._setup = True
+
+ def async_setup(self):
+ if not self._setuper:
+ self._setuper = threading.Thread(
+ target = self.setup)
+ self._setuper.start()
+
+ def async_setup_wait(self):
+ if not self._setup:
+ if self._setuper:
+ self._setuper.join()
+ if not self._setup:
+ raise RuntimeError, "Failed to setup application"
+ else:
+ self.setup()
def _make_home(self):
# Make sure all the paths are created where
if proc.wait():
raise RuntimeError, "Failed to set up application: %s %s" % (out,err,)
- def wait_dependencies(self, pidprobe=1, probe=10, pidmax=10):
+ def wait_dependencies(self, pidprobe=1, probe=0.5, pidmax=10, probemax=10):
if self.required_packages:
pidfile = self.DEPENDS_PIDFILE
server_key = self.server_key
):
time.sleep(probe)
+ probe = min(probemax, 1.5*probe)
def is_alive(self):
# Make sure all the paths are created where
import os.path
import rspawn
import subprocess
+import threading
from nepi.util import server
self.home_path = home_path
+ self._launcher = None
self._started = False
self._pid = None
self._ppid = None
if proc.wait():
raise RuntimeError, "Failed to set up TUN forwarder: %s %s" % (out,err,)
-
def launch(self, check_proto, listen, extra_args=[]):
peer = self.peer()
local = self.local()
)
if proc.wait():
- raise RuntimeError, "Failed to set up application: %s %s" % (out,err,)
+ raise RuntimeError, "Failed to set up TUN: %s %s" % (out,err,)
self._started = True
+
+ def async_launch(self, check_proto, listen, extra_args=[]):
+ if not self._launcher:
+ self._launcher = threading.Thread(
+ target = self.launch,
+ args = (check_proto, listen, extra_args))
+ self._launcher.start()
+
+ def async_launch_wait(self):
+ if not self._started:
+ if self._launcher:
+ self._launcher.join()
+ if not self._started:
+ raise RuntimeError, "Failed to launch TUN forwarder"
+ else:
+ self.launch()
def checkpid(self):
local = self.local()
pass
def setup(self):
- self.launch('udp', False, ("-U",))
+ self.launch_async('udp', False, ("-U",))
def shutdown(self):
self.kill()
def prepare(self):
if self.listening:
- self.launch('tcp', True)
+ self.async_launch('tcp', True)
def setup(self):
if not self.listening:
+ # make sure our peer is ready
+ peer = self.peer()
+ if peer and peer.peer_proto_impl:
+ peer.peer_proto_impl.async_launch_wait()
+
self.launch('tcp', False)
+ else:
+ # make sure WE are ready
+ self.async_launch_wait()
self.checkpid()
ERROR_LEVEL = 0
DEBUG_LEVEL = 1
+TRACE = False
if hasattr(os, "devnull"):
DEV_NULL = os.devnull
"""
Executes a remote commands, returns ((stdout,stderr),process)
"""
+ if TRACE:
+ print "ssh", host, command
+
tmp_known_hosts = None
args = ['ssh',
# Don't bother with localhost. Makes test easier
in which case it is advised that the destination be a folder.
"""
+ if TRACE:
+ print "scp", source, dest
+
if isinstance(source, file) or isinstance(dest, file) \
or hasattr(source, 'read') or hasattr(dest, 'write'):
assert not recursive