aboutsummaryrefslogtreecommitdiff
path: root/steuermann/run_cron.py
blob: b007d0f556da4a0e32db1a00142140922c3543f2 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
import os
import sys
import time
import steuermann.config
import steuermann.run
import datetime

# bugs:
# - this is a hideous hack that works around run.py not being designed for this
# - the work directory on the target machine is poorly named
#

class fakenode(object): 
    pass

def main() :

    if len(sys.argv) < 4 :
        print("smcron host name command")
        print("(from ",sys.argv,")")
        sys.exit(1)

    host = sys.argv[1]
    name = sys.argv[2]
    script = ' '.join(sys.argv[3:])

    db = steuermann.config.open_db()

    c = db.cursor()

    start_time = datetime.datetime.now()
    day, tod = str(start_time).split(' ')

    name = name + '--' + tod

    logfile = '%s/%s.%s' % (day, host, name)

    # something to reduce the possibility of a collision to very small - in this case, we assume that 
    # we can't start multiple processes at the same time from the same process number.  i.e. the
    # pid can not wrap in less than 1 clock tick
    decollision = os.getpid()

    c.execute("INSERT INTO sm_crons ( host, name, start_time, logfile, decollision ) VALUES ( ?, ?, ?, ?, ? )",
        ( host, name, str(start_time), logfile, decollision ) )
    db.commit()

    # this is a hideous hack to plug on to an interface that was not designed for this

    node = fakenode()
    node.host = host
    node.name = 'cron.' + name
    node.table = None
    node.cmd = None
    node.script = script
    node.resources = { }
    if host == 'localhost' :
        node.script_type = 'l'  # local
    else :
        node.script_type = 'r'  # remote
    
    hosts_ini = os.path.join(os.path.dirname(__file__), 'hosts.ini')

    if os.path.exists(steuermann.config.hosts_config):
        hosts_ini = steuermann.config.hosts_config

    runner = steuermann.run.runner( nodes = { node.name : node }, hosts_ini = hosts_ini )

    logname = logfile_name = steuermann.config.logdir + '/cron/' + logfile
    st = runner.run( node=node, run_name='', logfile_name = logname )

    if st == 'D' :
        fp = open(logname,"w")
        fp.write('execution on host is disabled in hosts.ini\n')
        fp.close()
        status = 'S'

    elif st == 'M' :
        fp = open(logname,"w")
        fp.write('host is at max proc limit - how did this happen?')
        fp.close()
        status = '?'

    elif st == 'R' :
        n = 0.1
        while 1 :
            exited = runner.poll()
            if exited :
                break
            if n < 2.0 :
                n = n * 2.0
            time.sleep(n)

        status = exited[1]

    end_time = datetime.datetime.now()
    td = end_time - start_time

    # only 1 decimal place because we don't poll often enough to make more reasonable.
    td = "%.1f" % ( td.microseconds/1e6 + td.seconds + td.days * 24 * 3600 )
    c.execute("UPDATE sm_crons SET end_time = ?, status = ?, duration = ? WHERE host = ? AND name = ? ",
        (str(end_time), status, td, host, name ) )
    db.commit()