32
from common import (util, studpath, chat)
32
from common import (util, studpath, chat, console)
36
trampoline_path = os.path.join(conf.ivle_install_dir, "bin/trampoline")
37
python_path = "/usr/bin/python" # Within jail
38
console_dir = "/opt/ivle/scripts" # Within jail
39
console_path = "/opt/ivle/scripts/python-console" # Within jail
42
37
"""Handler for the Console Service AJAX backend application."""
43
38
if len(req.path) > 0 and req.path[-1] == os.sep:
84
81
jail_path = os.path.join(conf.jail_base, req.user.login)
85
(host, port, magic) = start_console(uid, jail_path, working_dir)
82
cons = console.Console(uid, jail_path, working_dir)
87
84
# Assemble the key and return it.
88
key = cjson.encode({"host": host, "port": port, "magic": magic})
86
{"host": cons.host, "port": cons.port, "magic": cons.magic})
89
87
req.write(cjson.encode(key.encode("hex")))
91
89
def handle_chat(req, kind = "chat"):
142
140
req.content_type = "text/plain"
143
141
req.write(response)
145
def start_console(uid, jail_path, working_dir):
146
"""Starts up a console service for user uid, inside chroot jail jail_path
147
with work directory of working_dir
148
Returns a tupple (host, port, magic)
151
# TODO: Figure out the host name the console server is running on.
152
host = socket.gethostname()
156
magic = md5.new(uuid.uuid4().bytes).digest().encode('hex')
158
# Try to find a free port on the server.
159
# Just try some random ports in the range [3000,8000)
160
# until we either succeed, or give up. If you think this
161
# sounds risky, it isn't:
162
# For N ports (e.g. 5000) with k (e.g. 100) in use, the
163
# probability of failing to find a free port in t (e.g. 5) tries
164
# is (k / N) ** t (e.g. 3.2*10e-9).
168
port = int(random.uniform(3000, 8000))
170
# Start the console server (port, magic)
171
# trampoline usage: tramp uid jail_dir working_dir script_path args
172
# console usage: python-console port magic
173
cmd = ' '.join([trampoline_path, str(uid), jail_path,
174
console_dir, python_path, console_path,
175
str(port), str(magic), working_dir])
185
# If we can't start the console after 5 attemps (can't find a free port
186
# during random probing, syntax errors, segfaults) throw an exception.
188
raise Exception, "unable to start console service!"
190
return (host, port, magic)
192
143
def restart_console(uid, jail_path, working_dir, reason):
193
144
"""Tells the client that it must be issued a new console since the old
194
145
console is no longer availible. The client must accept the new key.
195
146
Returns the JSON response to be given to the client.
197
148
# Start a new console server console
198
(host, port, magic) = start_console(uid, jail_path, working_dir)
149
cons = console.Console(uid, jail_path, working_dir)
200
151
# Make a JSON object to tell the browser to restart its console client
201
new_key = cjson.encode({"host": host, "port": port, "magic": magic})
152
new_key = cjson.encode(
153
{"host": cons.host, "port": cons.port, "magic": cons.magic})
203
155
"restart": reason,
204
156
"key": new_key.encode("hex"),
207
159
return cjson.encode(json_restart)