This repository has been archived by the owner on Feb 19, 2021. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathstart.py
208 lines (165 loc) · 6.79 KB
/
start.py
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
from flask import Flask
from flask import render_template
from flask import request
from flask import jsonify
import docker
import subprocess
from subprocess import PIPE
import tarfile
import StringIO
import time
import datetime
from cdomain import crossdomain
from config import *
# code to fetch files and timestamp written as png
list_files_code = """import os, datetime
for file in os.listdir("."):
if file.endswith(".png"):
timestamp = str(datetime.datetime.fromtimestamp(os.path.getmtime(file))).split('.')[0]
print file, timestamp
"""
fig_manager = """
dpi = 80
from matplotlib import _pylab_helpers
fig_managers = _pylab_helpers.Gcf.get_all_fig_managers()
for idx, figman in enumerate(fig_managers):
figman.canvas.figure.savefig('image{0}.png'.format(idx), dpi=80)
"""
matplotlib_backend = """
# import matplotlib
# matplotlib.use('Agg')
"""
app = Flask(__name__)
def num_of_containers_running(c):
container_data = c.containers(quiet=True, all=False, trunc=True, latest=False, since=None,
before=None, limit=0)
return len(container_data)
def dock(code):
c = docker.Client(base_url=socket, version=version, timeout=timeout)
# check number of containers already running
containers_running = num_of_containers_running(c)
if (containers_running >= max_queue_size):
return {'busy': 'True'}, '', ''
# open STDIN
container = c.create_container(image, command='timeout 20 python', hostname=None, user=None,
detach=False, stdin_open=True, tty=False, mem_limit=0,
ports=None, environment=None, dns=None, volumes=None,
volumes_from=None, network_disabled=True, name=None,
entrypoint=None, cpu_shares=None, working_dir=None,)
container_id = container.get('Id');
if container_id is None:
print "Failed to create container!"
return -1
# DEBUG
if(debug): print "container_id is ", container_id
start = c.start(container, binds=None, port_bindings=None, lxc_conf=None,
publish_all_ports=False, links=None, privileged=False,)
if(debug):
print "start handle for container", start
print "Container list after START, before attach"
print c.containers(quiet=False, all=False, trunc=True, latest=False, since=None,
before=None, limit=-1),'\n'
# Attach handles for accessing the child's streams
handle = subprocess.Popen(['docker', 'attach', container_id], stdin=PIPE,
stdout=PIPE, stderr=PIPE,)
if(debug):
print "Container list after ATTACH, before sending code"
print c.containers(quiet=False, all=False, trunc=True, latest=False, since=None,
before=None, limit=-1), '\n'
# Send code for execution, separate STDOUT and STDERR
stdout, stderr = handle.communicate(code)
lines = stdout.split('\n')
# some ninja-python
stdout = '\n'.join(lines[:max_output]) + '\n...' if len(lines) > max_output else stdout
# Wait for container to finish eecuting code and exit
exitcode = c.wait(container)
# DEBUG
if(debug):
print "code ", code
print "EXITCODE after exec ", exitcode
print "STDOUT after exec ", stdout
print "STDERR after exec ", stderr
print "Containers after execution"
print c.containers(quiet=False, all=False, trunc=True, latest=False, since=None,
before=None, limit=-1), '\n'
####################################################################################
# Handle error messages based on exit-code
if exitcode != 0:
# Code for timeout
if exitcode == 124:
stderr = stderr + 'Run-time limit exceeded'
# http://adelqod.blogspot.com/2013/05/error-code-139-on-linux.html
elif exitcode == 139:
stderr = stderr + 'Segmentation Fault'
# Fetch files generated
## Travel the docker filesystem default directory for files of our interest
start = c.restart(container)
# Generate Handle for accessing the child's streams
handle = subprocess.Popen(['docker', 'attach', container_id], stdin=subprocess.PIPE,
stdout=subprocess.PIPE, stderr=subprocess.PIPE,)
# Separate STDOUT and STDERR
out, err = handle.communicate(list_files_code);
# Wait for container to finish executing code and exit
exitcode = c.wait(container)
# DEBUG
if (debug):
print "List of files returned in STDOUT ", out
print "STDERR after exec ", err
# Get list of files, last value is an empty string
filelist = [i.split(' ') for i in out.split('\n')[:-1]]
filelist = [[i[0], i[1] + ' ' + i[2]] for i in filelist]
# dict of UUencoded filecontent to be returned
# UUDECODE is difficult client side, so we go the base64 route
# fcencode = {}
# dict of base64 converted filecontent to be returned
fcbase64 = {}
# iterate for all files in the list
import base64
for f in filelist:
# first index is the filename, next is the timestamp
filename = f[0]
timestamp = f[1]
copy = c.copy(container, filename)
ofile = StringIO.StringIO()
while 1:
try:
ofile.write(next(copy))
except StopIteration:
ofile.seek(0)
tarf = tarfile.TarFile(fileobj=ofile)
fcontent = tarf.extractfile(filename).read()
# DEBUG to check if output is correct before encoding
# print fcontent
# UUDECODE is difficult client side, so we go the base64 route
# fcencode[f] = fcontent.encode("uu")
fcbase64[filename] = base64.b64encode(fcontent)
# add file creation timestamp
fcbase64[filename + 'timestamp'] = timestamp
break
finally:
pass
return fcbase64, stdout, stderr
@app.route('/')
def home():
return 'The server is up!'
@app.route('/code')
def write_code():
return render_template('runcode.html')
@app.route('/runcode', methods=['POST'])
# @crossdomain(origin='*', headers='Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept')
@crossdomain(origin='*', headers='Content-Type, X-Requested-With, Accept')
def run_code():
content = request.json['data']
# DEBUG
# print content
# fire up docker
# force matplotlib to agg and add the figure manager code
content = matplotlib_backend + content + fig_manager
if(debug): print content
result, stdout, stderr = dock(content)
# print "****************result", result
timestamp = time.time()
timestamp = datetime.datetime.fromtimestamp(timestamp).strftime('%Y-%m-%d %H:%M:%S')
return jsonify(result=result, stdout=stdout, stderr=stderr, timestamp=timestamp)
if __name__ == '__main__':
app.run(host=hostip, port=port, debug=True, threaded=threaded)