#!/usr/bin/python2.6
from __future__ import print_function
from subprocess import PIPE, Popen, STDOUT, check_call
import time, datetime, sys, os
from optparse import OptionParser

# global vars
options = None
globallog = None

def makelog(nodename):
    p = list(os.path.split(options.logfn))
    fn = p.pop()
    l = fn.split(".")
    l.insert(1, nodename)
    fn = '.'.join(l)
    p.append(fn)
    return open(os.path.join(*p), "a", buffering=1)

def starterl(nodename):
    args = [options.erlbin]
    if nodename is not None: 
        args.append('-sname')
        args.append(nodename)
    args += options.erloptions.split(' ')
    if not options.nodelog:
        logfile = globallog
    else:
        logfile = makelog(nodename)
    return Popen(args, executable=options.erlbin, bufsize=1, stdout=logfile, 
                 stderr=STDOUT, close_fds=True)
    
def numconns():
    cmd = 'netstat -tnap'
    out=Popen(cmd, stdout=PIPE, stderr=PIPE, shell=True).communicate()[0]
    n = len([l for l in out.split("\n") if l.find("beam.smp") != -1])
    return n
    
def main():
    global options
    parser = OptionParser()
    parser.add_option("-c", "--start-nodes", dest="startnodes", 
                      default=10, type="int",
                      help="number of nodes to start, default: 10"
        )
    parser.add_option("-l", "--logfn", dest="logfn", default="/tmp/mass-start-erl.log",
                      help="log output to LOG")
    parser.add_option("-m", "--node-log", dest="nodelog", action="store_true", 
                      default=False,
                      help="log messages go to one file per VM, default: use single file (line buffered)"
                      )
    parser.add_option("-n", "--node-name", dest="nodename",
                      help="template for nodename of the form 'n-%s', where %s is replaced with a counter; "
                      "if unset, node starts without a name"
        )
    parser.add_option("-b", "--erlbin", dest="erlbin", default="/usr/bin/erl",
                      help="path to erlang binary, default: /usr/bin/erl"
                      )
    parser.add_option("-e", "--erlopts", dest="erloptions",
                      default="+B -noinput",
                      help="options passed verbatim to the erl binary (dont forget to quote), defaults to '+B -noinput', "
                      "disabling reading from stdin and Erlangs signal handling")
    parser.add_option("-t", "--time-to-live", dest="timetolive",
                      default=0, type="int",
                      help="kill VMs after timeout seconds, default: live forever"
                      )
    parser.add_option("-s", "--sleep", dest="sleep", 
                      default="1", type=int,
                      help="slow startup: sleep seconds between VM starts, default 1"
                      )
    (options, args) = parser.parse_args(sys.argv)
    global globallog
    globallog = open(options.logfn, "a", buffering=1)
    def log(msg):
        d = datetime.datetime.now()
        print(str(d) + " " + msg, file=globallog)
    cnt = 0
    plist = []
    while cnt < options.startnodes:
        cnt += 1
        n = None
        if options.nodename:           
            if options.nodename.find("%s") == -1:
                print("Error: nodename must contain a %s marker (but is set to: %s)" % 
                      options.nodename,
                      file=sys.stderr
                )
                sys.exit(-1)
            n = options.nodename % cnt
        p = starterl(n)
        plist.append(p)
        #n = numconns()
        #log("started node %s, number of connections: %s" % (cnt, n))
        log("started node %s" % cnt)
        time.sleep(options.sleep)

    if options.timetolive:
        time.sleep(options.timetolive)
        log("times up! killing VMs")
        def t(p):
            p.terminate()
        map(t, plist)
    else:
        def f(p):
            p.wait()
        map(f, plist)

if __name__ == '__main__': 
    main()

    