From: Brian Warner Date: Wed, 11 Jul 2007 02:05:18 +0000 (-0700) Subject: runner.py: further refactoring X-Git-Url: https://git.rkrishnan.org/Site/Content/Exhibitors/nxhtml.html?a=commitdiff_plain;h=f22801aa3396800eb04818aae7d96f8d84188908;p=tahoe-lafs%2Ftahoe-lafs.git runner.py: further refactoring --- diff --git a/src/allmydata/scripts/create_node.py b/src/allmydata/scripts/create_node.py new file mode 100644 index 00000000..5eb1b092 --- /dev/null +++ b/src/allmydata/scripts/create_node.py @@ -0,0 +1,80 @@ + +import os, sys +from twisted.python import usage +from allmydata.scripts.common import NoDefaultBasedirMixin + +class CreateClientOptions(NoDefaultBasedirMixin, usage.Options): + optParameters = [ + ["basedir", "C", None, "which directory to create the client in"], + ] + +class CreateIntroducerOptions(NoDefaultBasedirMixin, usage.Options): + optParameters = [ + ["basedir", "C", None, "which directory to create the introducer in"], + ] + +client_tac = """ +# -*- python -*- + +from allmydata import client +from twisted.application import service + +c = client.Client() + +application = service.Application("allmydata_client") +c.setServiceParent(application) +""" + +introducer_tac = """ +# -*- python -*- + +from allmydata import introducer_and_vdrive +from twisted.application import service + +c = introducer_and_vdrive.IntroducerAndVdrive() + +application = service.Application("allmydata_introducer") +c.setServiceParent(application) +""" + +def create_client(basedir, config, out=sys.stdout, err=sys.stderr): + if os.path.exists(basedir): + if os.listdir(basedir): + print >>err, "The base directory already exists: %s" % basedir + print >>err, "To avoid clobbering anything, I am going to quit now" + print >>err, "Please use a different directory, or delete this one" + return -1 + # we're willing to use an empty directory + else: + os.mkdir(basedir) + f = open(os.path.join(basedir, "client.tac"), "w") + f.write(client_tac) + f.close() + print >>out, "client created in %s" % basedir + print >>out, " please copy introducer.furl and vdrive.furl into the directory" + +def create_introducer(basedir, config, out=sys.stdout, err=sys.stderr): + if os.path.exists(basedir): + if os.listdir(basedir): + print >>err, "The base directory already exists: %s" % basedir + print >>err, "To avoid clobbering anything, I am going to quit now" + print >>err, "Please use a different directory, or delete this one" + return -1 + # we're willing to use an empty directory + else: + os.mkdir(basedir) + f = open(os.path.join(basedir, "introducer.tac"), "w") + f.write(introducer_tac) + f.close() + print >>out, "introducer created in %s" % basedir + +subCommands = [ + ["create-client", None, CreateClientOptions, "Create a client node."], + ["create-introducer", None, CreateIntroducerOptions, "Create a introducer node."], + +] + +dispatch = { + "create-client": create_client, + "create-introducer": create_introducer, + } diff --git a/src/allmydata/scripts/runner.py b/src/allmydata/scripts/runner.py index 0349fa24..deb852b8 100644 --- a/src/allmydata/scripts/runner.py +++ b/src/allmydata/scripts/runner.py @@ -1,102 +1,9 @@ -import os, subprocess, sys, signal, time +import sys from cStringIO import StringIO from twisted.python import usage -from twisted.python.procutils import which -from allmydata.scripts import debug -from allmydata.scripts.common import BasedirMixin, NoDefaultBasedirMixin - -def testtwistd(loc): - try: - return subprocess.call(["python", loc,], stdout=subprocess.PIPE, stderr=subprocess.PIPE) - except: - return -1 - -twistd = None -if not twistd: - for maybetwistd in which("twistd"): - ret = testtwistd(maybetwistd) - if ret == 0: - twistd = maybetwistd - break - -if not twistd: - for maybetwistd in which("twistd.py"): - ret = testtwistd(maybetwistd) - if ret == 0: - twistd = maybetwistd - break - -if not twistd: - maybetwistd = os.path.join(sys.prefix, 'Scripts', 'twistd') - ret = testtwistd(maybetwistd) - if ret == 0: - twistd = maybetwistd - -if not twistd: - maybetwistd = os.path.join(sys.prefix, 'Scripts', 'twistd.py') - ret = testtwistd(maybetwistd) - if ret == 0: - twistd = maybetwistd - -if not twistd: - print "Can't find twistd (it comes with Twisted). Aborting." - sys.exit(1) - -class StartOptions(BasedirMixin, usage.Options): - optParameters = [ - ["basedir", "C", None, "which directory to start the node in"], - ] - -class StopOptions(BasedirMixin, usage.Options): - optParameters = [ - ["basedir", "C", None, "which directory to stop the node in"], - ] - -class RestartOptions(BasedirMixin, usage.Options): - optParameters = [ - ["basedir", "C", None, "which directory to restart the node in"], - ] - optFlags = [ - ["force", "f", "if the node is not already running, start it " - "instead of complaining that you should have used 'start' instead " - "of 'restart'"], - ] - -class CreateClientOptions(NoDefaultBasedirMixin, usage.Options): - optParameters = [ - ["basedir", "C", None, "which directory to create the client in"], - ] - -class CreateIntroducerOptions(NoDefaultBasedirMixin, usage.Options): - optParameters = [ - ["basedir", "C", None, "which directory to create the introducer in"], - ] - -client_tac = """ -# -*- python -*- - -from allmydata import client -from twisted.application import service - -c = client.Client() - -application = service.Application("allmydata_client") -c.setServiceParent(application) -""" - -introducer_tac = """ -# -*- python -*- - -from allmydata import introducer_and_vdrive -from twisted.application import service - -c = introducer_and_vdrive.IntroducerAndVdrive() - -application = service.Application("allmydata_introducer") -c.setServiceParent(application) -""" +from allmydata.scripts import debug, create_node, startstop_node class Options(usage.Options): synopsis = "Usage: allmydata [command options]" @@ -105,13 +12,10 @@ class Options(usage.Options): ["quiet", "q", "operate silently"], ] - subCommands = [ - ["create-client", None, CreateClientOptions, "Create a client node."], - ["create-introducer", None, CreateIntroducerOptions, "Create a introducer node."], - ["start", None, StartOptions, "Start a node (of any type)."], - ["stop", None, StopOptions, "Stop a node."], - ["restart", None, RestartOptions, "Restart a node."], - ] + debug.subCommands + subCommands = [] + subCommands += create_node.subCommands + subCommands += startstop_node.subCommands + subCommands += debug.subCommands def postOptions(self): if not hasattr(self, 'subOptions'): @@ -137,29 +41,12 @@ def runner(argv, run_by_human=True, stdout=sys.stdout, stderr=sys.stderr): stdout = StringIO() rc = 0 - if command == "create-client": - for basedir in so.basedirs: - rc = create_client(basedir, so, stdout, stderr) or rc - elif command == "create-introducer": - for basedir in so.basedirs: - rc = create_introducer(basedir, so, stdout, stderr) or rc - elif command == "start": + if command in create_node.dispatch: for basedir in so.basedirs: - rc = start(basedir, so, stdout, stderr) or rc - elif command == "stop": - for basedir in so.basedirs: - rc = stop(basedir, so, stdout, stderr) or rc - elif command == "restart": - for basedir in so.basedirs: - rc = stop(basedir, so, stdout, stderr) or rc - if rc == 2 and so['force']: - print >>stderr, "ignoring couldn't-stop" - rc = 0 - if rc: - print >>stderr, "not restarting" - return rc - for basedir in so.basedirs: - rc = start(basedir, so, stdout, stderr) or rc + f = create_node.dispatch[command] + rc = f(basedir, so, stdout, stderr) or rc + elif command in startstop_node.dispatch: + rc = startstop_node.dispatch[command](so, stdout, stderr) elif command in debug.dispatch: rc = debug.dispatch[command](so, stdout, stderr) @@ -168,79 +55,3 @@ def runner(argv, run_by_human=True, stdout=sys.stdout, stderr=sys.stderr): def run(): rc = runner(sys.argv[1:]) sys.exit(rc) - -def create_client(basedir, config, out=sys.stdout, err=sys.stderr): - if os.path.exists(basedir): - if os.listdir(basedir): - print >>err, "The base directory already exists: %s" % basedir - print >>err, "To avoid clobbering anything, I am going to quit now" - print >>err, "Please use a different directory, or delete this one" - return -1 - # we're willing to use an empty directory - else: - os.mkdir(basedir) - f = open(os.path.join(basedir, "client.tac"), "w") - f.write(client_tac) - f.close() - print >>out, "client created in %s" % basedir - print >>out, " please copy introducer.furl and vdrive.furl into the directory" - -def create_introducer(basedir, config, out=sys.stdout, err=sys.stderr): - if os.path.exists(basedir): - if os.listdir(basedir): - print >>err, "The base directory already exists: %s" % basedir - print >>err, "To avoid clobbering anything, I am going to quit now" - print >>err, "Please use a different directory, or delete this one" - return -1 - # we're willing to use an empty directory - else: - os.mkdir(basedir) - f = open(os.path.join(basedir, "introducer.tac"), "w") - f.write(introducer_tac) - f.close() - print >>out, "introducer created in %s" % basedir - -def start(basedir, config, out=sys.stdout, err=sys.stderr): - print >>out, "STARTING", basedir - if os.path.exists(os.path.join(basedir, "client.tac")): - tac = "client.tac" - type = "client" - elif os.path.exists(os.path.join(basedir, "introducer.tac")): - tac = "introducer.tac" - type = "introducer" - else: - print >>err, "%s does not look like a node directory" % basedir - if not os.path.isdir(basedir): - print >>err, " in fact, it doesn't look like a directory at all!" - sys.exit(1) - rc = subprocess.call(["python", twistd, "-y", tac,], cwd=basedir) - if rc == 0: - print >>out, "%s node probably started" % type - return 0 - else: - print >>err, "%s node probably not started" % type - return 1 - -def stop(basedir, config, out=sys.stdout, err=sys.stderr): - print >>out, "STOPPING", basedir - pidfile = os.path.join(basedir, "twistd.pid") - if not os.path.exists(pidfile): - print >>err, "%s does not look like a running node directory (no twistd.pid)" % basedir - return 2 - pid = open(pidfile, "r").read() - pid = int(pid) - - timer = 0 - os.kill(pid, signal.SIGTERM) - time.sleep(0.1) - while timer < 5: - # poll once per second until twistd.pid goes away, up to 5 seconds - try: - os.kill(pid, 0) - except OSError: - print >>out, "process %d is dead" % pid - return - timer += 1 - time.sleep(1) - print >>err, "never saw process go away" - return 1 diff --git a/src/allmydata/scripts/startstop_node.py b/src/allmydata/scripts/startstop_node.py new file mode 100644 index 00000000..5f73cd64 --- /dev/null +++ b/src/allmydata/scripts/startstop_node.py @@ -0,0 +1,149 @@ + +import os, sys, signal, time, subprocess +from twisted.python import usage +from allmydata.scripts.common import BasedirMixin +from twisted.python.procutils import which + +class StartOptions(BasedirMixin, usage.Options): + optParameters = [ + ["basedir", "C", None, "which directory to start the node in"], + ] + +class StopOptions(BasedirMixin, usage.Options): + optParameters = [ + ["basedir", "C", None, "which directory to stop the node in"], + ] + +class RestartOptions(BasedirMixin, usage.Options): + optParameters = [ + ["basedir", "C", None, "which directory to restart the node in"], + ] + optFlags = [ + ["force", "f", "if the node is not already running, start it " + "instead of complaining that you should have used 'start' instead " + "of 'restart'"], + ] + + +def testtwistd(loc): + try: + return subprocess.call(["python", loc,], stdout=subprocess.PIPE, stderr=subprocess.PIPE) + except: + return -1 + +twistd = None +if not twistd: + for maybetwistd in which("twistd"): + ret = testtwistd(maybetwistd) + if ret == 0: + twistd = maybetwistd + break + +if not twistd: + for maybetwistd in which("twistd.py"): + ret = testtwistd(maybetwistd) + if ret == 0: + twistd = maybetwistd + break + +if not twistd: + maybetwistd = os.path.join(sys.prefix, 'Scripts', 'twistd') + ret = testtwistd(maybetwistd) + if ret == 0: + twistd = maybetwistd + +if not twistd: + maybetwistd = os.path.join(sys.prefix, 'Scripts', 'twistd.py') + ret = testtwistd(maybetwistd) + if ret == 0: + twistd = maybetwistd + +if not twistd: + print "Can't find twistd (it comes with Twisted). Aborting." + sys.exit(1) + + + +def do_start(basedir, config, out=sys.stdout, err=sys.stderr): + print >>out, "STARTING", basedir + if os.path.exists(os.path.join(basedir, "client.tac")): + tac = "client.tac" + type = "client" + elif os.path.exists(os.path.join(basedir, "introducer.tac")): + tac = "introducer.tac" + type = "introducer" + else: + print >>err, "%s does not look like a node directory" % basedir + if not os.path.isdir(basedir): + print >>err, " in fact, it doesn't look like a directory at all!" + sys.exit(1) + rc = subprocess.call(["python", twistd, "-y", tac,], cwd=basedir) + if rc == 0: + print >>out, "%s node probably started" % type + return 0 + else: + print >>err, "%s node probably not started" % type + return 1 + +def do_stop(basedir, config, out=sys.stdout, err=sys.stderr): + print >>out, "STOPPING", basedir + pidfile = os.path.join(basedir, "twistd.pid") + if not os.path.exists(pidfile): + print >>err, "%s does not look like a running node directory (no twistd.pid)" % basedir + return 2 + pid = open(pidfile, "r").read() + pid = int(pid) + + timer = 0 + os.kill(pid, signal.SIGTERM) + time.sleep(0.1) + while timer < 5: + # poll once per second until twistd.pid goes away, up to 5 seconds + try: + os.kill(pid, 0) + except OSError: + print >>out, "process %d is dead" % pid + return + timer += 1 + time.sleep(1) + print >>err, "never saw process go away" + return 1 + +def start(config, stdout, stderr): + rc = 0 + for basedir in config['basedirs']: + rc = do_start(basedir, config, stdout, stderr) or rc + return rc + +def stop(config, stdout, stderr): + rc = 0 + for basedir in config['basedirs']: + rc = do_stop(basedir, config, stdout, stderr) or rc + return rc + +def restart(config, stdout, stderr): + rc = 0 + for basedir in config['basedirs']: + rc = do_stop(basedir, config, stdout, stderr) or rc + if rc == 2 and config['force']: + print >>stderr, "ignoring couldn't-stop" + rc = 0 + if rc: + print >>stderr, "not restarting" + return rc + for basedir in config['basedirs']: + rc = do_start(basedir, config, stdout, stderr) or rc + return rc + + +subCommands = [ + ["start", None, StartOptions, "Start a node (of any type)."], + ["stop", None, StopOptions, "Stop a node."], + ["restart", None, RestartOptions, "Restart a node."], +] + +dispatch = { + "start": start, + "stop": stop, + "restart": restart, + }