~azzar1/unity/add-show-desktop-key

« back to all changes in this revision

Viewing changes to ivle/console.py

  • Committer: Nick Chadwick
  • Date: 2009-02-24 03:32:59 UTC
  • mto: (1099.1.227 exercise-ui)
  • mto: This revision was merged to the branch mainline in revision 1162.
  • Revision ID: chadnickbok@gmail.com-20090224033259-m518nuqp6w9f23ax
Added a new page to display exercises. This will then be modified to
actually edit exercises.

Show diffs side-by-side

added added

removed removed

Lines of Context:
23
23
 
24
24
import errno
25
25
import cPickle
26
 
import hashlib
 
26
import md5
27
27
import os
28
28
import random
29
29
import socket
30
30
import StringIO
31
31
import uuid
32
32
 
33
 
from ivle import chat, interpret
 
33
import cjson
 
34
 
 
35
import ivle.conf
 
36
from ivle import (chat, util)
 
37
 
 
38
# Outside Jail
 
39
trampoline_path = os.path.join(ivle.conf.lib_path, "trampoline")
 
40
# Inside Jail
 
41
python_path = "/usr/bin/python"
 
42
console_dir = os.path.join(ivle.conf.share_path, 'services')
 
43
console_path = os.path.join(console_dir, 'python-console')
34
44
 
35
45
class ConsoleError(Exception):
36
46
    """ The console failed in some way. This is bad. """
37
 
    pass
 
47
    def __init__(self, value):
 
48
        self.value = value
 
49
    def __str__(self):
 
50
        return repr(self.value)
38
51
 
39
52
class ConsoleException(Exception):
40
53
    """ The code being exectuted on the console returned an exception. 
41
54
    """
42
 
    pass
 
55
    def __init__(self, value):
 
56
        self.value = value
 
57
    def __str__(self):
 
58
        return repr(self.value)
43
59
 
44
60
class TruncateStringIO(StringIO.StringIO):
45
61
    """ A class that wraps around StringIO and truncates the buffer when the 
106
122
class Console(object):
107
123
    """ Provides a nice python interface to the console
108
124
    """
109
 
    def __init__(self, config, user, jail_path, working_dir):
 
125
    def __init__(self, uid, jail_path, working_dir):
110
126
        """Starts up a console service for user uid, inside chroot jail 
111
127
        jail_path with work directory of working_dir
112
128
        """
113
129
        super(Console, self).__init__()
114
130
 
115
 
        self.config = config
116
 
        self.user = user
 
131
        self.uid = uid
117
132
        self.jail_path = jail_path
118
133
        self.working_dir = working_dir
119
134
 
139
154
 
140
155
        # Create magic
141
156
        # TODO
142
 
        self.magic = hashlib.md5(uuid.uuid4().bytes).hexdigest()
 
157
        self.magic = md5.new(uuid.uuid4().bytes).digest().encode('hex')
143
158
 
144
159
        # Try to find a free port on the server.
145
160
        # Just try some random ports in the range [3000,8000)
150
165
        # is (k / N) ** t (e.g. 3.2*10e-9).
151
166
 
152
167
        tries = 0
153
 
        error = None
154
168
        while tries < 5:
155
169
            self.port = int(random.uniform(3000, 8000))
156
170
 
157
 
            python_console = os.path.join(self.config['paths']['share'],
158
 
                        'services/python-console')
159
 
            args = [python_console, str(self.port), str(self.magic)]
 
171
            # Start the console server (port, magic)
 
172
            # trampoline usage: tramp uid jail_dir working_dir script_path args
 
173
            # console usage:    python-console port magic
 
174
            res = os.spawnv(os.P_WAIT, trampoline_path, [
 
175
                trampoline_path,
 
176
                str(self.uid),
 
177
                ivle.conf.jail_base,
 
178
                ivle.conf.jail_src_base,
 
179
                ivle.conf.jail_system,
 
180
                self.jail_path,
 
181
                console_dir,
 
182
                python_path,
 
183
                console_path,
 
184
                str(self.port),
 
185
                str(self.magic),
 
186
                self.working_dir
 
187
                ])
160
188
 
161
 
            try:
162
 
                interpret.execute_raw(self.config, self.user, self.jail_path,
163
 
                        self.working_dir, "/usr/bin/python", args)
 
189
            if res == 0:
164
190
                # success
165
 
                break
166
 
            except interpret.ExecutionError, e:
167
 
                tries += 1
168
 
                error = e.message
169
 
 
170
 
        # If we can't start the console after 5 attemps (can't find a free 
171
 
        # port during random probing, syntax errors, segfaults) throw an 
172
 
        # exception.
 
191
                break;
 
192
 
 
193
            tries += 1
 
194
 
 
195
        # If we can't start the console after 5 attemps (can't find a free port 
 
196
        # during random probing, syntax errors, segfaults) throw an exception.
173
197
        if tries == 5:
174
 
            raise ConsoleError('Unable to start console service: %s'%error)
 
198
            raise ConsoleError("Unable to start console service!")
175
199
 
176
200
    def __chat(self, cmd, args):
177
201
        """ A wrapper around chat.chat to comunicate directly with the 
188
212
            else:
189
213
                # Some other error - probably serious
190
214
                raise socket.error, (enumber, estring)
191
 
        except ValueError:
 
215
        except cjson.DecodeError:
192
216
            # Couldn't decode the JSON
193
217
            raise ConsoleError(
194
218
                "Could not understand the python console response")
195
 
        except chat.ProtocolError, e:
196
 
            raise ConsoleError(*e.args)
197
219
 
198
220
        return response
199
221
 
247
269
 
248
270
        # Unpickle the globals
249
271
        for g in globals['globals']:
250
 
            globals['globals'][g] = cPickle.loads(str(globals['globals'][g]))
 
272
            globals['globals'][g] = cPickle.loads(globals['globals'][g])
251
273
 
252
274
        return globals['globals']
253
275
        
266
288
        # Unpickle any exceptions
267
289
        if 'exception' in call:
268
290
            call['exception']['except'] = \
269
 
                cPickle.loads(str(call['exception']['except']))
 
291
                cPickle.loads(call['exception']['except'])
270
292
 
271
293
        return call
272
294
 
278
300
              
279
301
        # Unpickle any exceptions
280
302
        if 'exception' in execute:
281
 
            execute['exception'] = cPickle.loads(str(execute['exception']))
282
 
        return execute
 
303
            return cPickle.loads(execute['exception'])
 
304
        else:
 
305
            return execute
283
306
 
284
307
 
285
308
    def set_vars(self, variables):