1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 """
24 This module executes pickled jobs on the cluster.
25
26 @author: Christian Widmer
27 @author: Cheng Soon Ong
28 @author: Dan Blanchard (dblanchard@ets.org)
29 """
30
31 from __future__ import absolute_import, print_function, unicode_literals
32
33 import argparse
34 import os
35 import sys
36
37 from redis import StrictRedis
38
39 from gridmap.data import clean_path, zload_db, zsave_db
40 from gridmap.job import REDIS_DB, REDIS_PORT
41
42
43 -def _run_job(uniq_id, job_num, temp_dir, redis_host):
44 """
45 Execute the pickled job and produce pickled output.
46
47 @param uniq_id: The unique suffix for the tables corresponding to this job
48 in the database.
49 @type uniq_id: C{basestring}
50 @param job_num: The index for this job's content in the job and output
51 tables.
52 @type job_num: C{int}
53 @param temp_dir: Local temporary directory for storing output for an
54 individual job.
55 @type temp_dir: C{basestring}
56 @param redis_host: Hostname of the database to connect to get the job data.
57 @type redis_host: C{basestring}
58 """
59
60 redis_server = StrictRedis(host=redis_host, port=REDIS_PORT, db=REDIS_DB)
61
62 print("Loading job...", end="", file=sys.stderr)
63 sys.stderr.flush()
64 try:
65 job = zload_db(redis_server, 'job_{0}'.format(uniq_id), job_num)
66 except Exception as detail:
67 job = None
68 print("FAILED", file=sys.stderr)
69
70 print("Writing exception to database for job {0}...".format(job_num),
71 end="", file=sys.stderr)
72 sys.stderr.flush()
73 zsave_db(detail, redis_server, 'output_{0}'.format(uniq_id), job_num)
74 print("done", file=sys.stderr)
75 else:
76 print("done", file=sys.stderr)
77
78 print("Running job...", end="", file=sys.stderr)
79 sys.stderr.flush()
80 job.execute()
81 print("done", file=sys.stderr)
82
83 print("Writing output to database for job {0}...".format(job_num),
84 end="", file=sys.stderr)
85 sys.stderr.flush()
86 zsave_db(job.ret, redis_server, 'output_{0}'.format(uniq_id), job_num)
87 print("done", file=sys.stderr)
88
89
90 if job.cleanup:
91 log_stdout_fn = os.path.join(temp_dir, '{0}.o{1}'.format(job.name,
92 job.jobid))
93 log_stderr_fn = os.path.join(temp_dir, '{0}.e{1}'.format(job.name,
94 job.jobid))
95
96 try:
97 os.remove(log_stdout_fn)
98 os.remove(log_stderr_fn)
99 except OSError:
100 pass
101
102
104 """
105 Parse the command line inputs and call _run_job
106 """
107
108
109 parser = argparse.ArgumentParser(description="This wrapper script will run \
110 a pickled Python function on \
111 some pickled data in a Redis\
112 database, " + "and write the\
113 results back to the database.\
114 You almost never want to run\
115 this yourself.",
116 formatter_class=argparse.ArgumentDefaultsHelpFormatter,
117 conflict_handler='resolve')
118 parser.add_argument('uniq_id',
119 help='The unique suffix for the tables corresponding to\
120 this job in the database.')
121 parser.add_argument('job_number',
122 help='Which job number should be run. Dictates which \
123 input data is read from database and where output\
124 data is stored.',
125 type=int)
126 parser.add_argument('module_dir',
127 help='Directory that contains module containing pickled\
128 function. This will get added to PYTHONPATH \
129 temporarily.')
130 parser.add_argument('temp_dir',
131 help='Directory that temporary output will be stored\
132 in.')
133 parser.add_argument('redis_host',
134 help='The hostname of the server that where the Redis\
135 database is.')
136 args = parser.parse_args()
137
138 print("Appended {0} to PYTHONPATH".format(args.module_dir), file=sys.stderr)
139 sys.path.append(clean_path(args.module_dir))
140
141
142 _run_job(args.uniq_id, args.job_number, clean_path(args.temp_dir),
143 args.redis_host)
144
145
146 if __name__ == "__main__":
147 _main()
148