2 import os, sys, signal, time
3 from twisted.python import usage
4 from allmydata.scripts.common import BasedirMixin
5 from allmydata.util import fileutil, find_exe
7 class StartOptions(BasedirMixin, usage.Options):
9 ["basedir", "C", None, "which directory to start the node in"],
12 ["profile", "p", "whether to run under the Python profiler, putting results in \"profiling_results.prof\""],
15 class StopOptions(BasedirMixin, usage.Options):
17 ["basedir", "C", None, "which directory to stop the node in"],
20 class RestartOptions(BasedirMixin, usage.Options):
22 ["basedir", "C", None, "which directory to restart the node in"],
25 ["force", "f", "if the node is not already running, start it "
26 "instead of complaining that you should have used 'start' instead "
28 ["profile", "p", "whether to run under the Python profiler, putting results in \"profiling_results.prof\""],
31 def do_start(basedir, profile=False, out=sys.stdout, err=sys.stderr):
32 print >>out, "STARTING", basedir
33 if os.path.exists(os.path.join(basedir, "client.tac")):
36 elif os.path.exists(os.path.join(basedir, "tahoe-client.tac")):
37 tac = "tahoe-client.tac"
39 elif os.path.exists(os.path.join(basedir, "introducer.tac")):
40 tac = "introducer.tac"
42 elif os.path.exists(os.path.join(basedir, "tahoe-introducer.tac")):
43 tac = "tahoe-introducer.tac"
46 print >>err, "%s does not look like a node directory" % basedir
47 if not os.path.isdir(basedir):
48 print >>err, " in fact, it doesn't look like a directory at all!"
51 cmd = find_exe.find_exe('twistd')
53 print "Can't find twistd (it comes with Twisted). Aborting."
56 fileutil.make_dirs(os.path.join(basedir, "logs"))
57 cmd.extend(["-y", tac, "--logfile", os.path.join("logs", "twistd.log")])
59 cmd.extend(["--profile=profiling_results.prof", "--savestats",])
63 rc = os.system(' '.join(cmd))
67 print >>out, "%s node probably started" % type
70 print >>err, "%s node probably not started" % type
73 def do_stop(basedir, out=sys.stdout, err=sys.stderr):
74 print >>out, "STOPPING", basedir
75 pidfile = os.path.join(basedir, "twistd.pid")
76 if not os.path.exists(pidfile):
77 print >>err, "%s does not look like a running node directory (no twistd.pid)" % basedir
79 pid = open(pidfile, "r").read()
82 # kill it hard (SIGKILL), delete the twistd.pid file, then wait for the
83 # process itself to go away. If it hasn't gone away after 5 seconds, warn
84 # the user but keep waiting until they give up.
86 os.kill(pid, signal.SIGKILL)
87 except OSError, oserr:
90 # the process didn't exist, so wipe the pid file
97 except EnvironmentError:
104 # poll once per second until we see the process is no longer running
108 print >>out, "process %d is dead" % pid
113 print >>err, ("It looks like pid %d is still running "
114 "after %d seconds" % (pid,
115 (time.time() - start)))
116 print >>err, "I will keep watching it until you interrupt me."
120 print >>err, "pid %d still running after %d seconds" % \
121 (pid, (time.time() - start))
126 def start(config, stdout, stderr):
128 for basedir in config['basedirs']:
129 rc = do_start(basedir, config['profile'], stdout, stderr) or rc
132 def stop(config, stdout, stderr):
134 for basedir in config['basedirs']:
135 rc = do_stop(basedir, stdout, stderr) or rc
138 def restart(config, stdout, stderr):
140 for basedir in config['basedirs']:
141 rc = do_stop(basedir, stdout, stderr) or rc
142 if rc == 2 and config['force']:
143 print >>stderr, "ignoring couldn't-stop"
146 print >>stderr, "not restarting"
148 for basedir in config['basedirs']:
149 rc = do_start(basedir, config['profile'], stdout, stderr) or rc
154 ["start", None, StartOptions, "Start a node (of any type)."],
155 ["stop", None, StopOptions, "Stop a node."],
156 ["restart", None, RestartOptions, "Restart a node."],