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

« back to all changes in this revision

Viewing changes to ivle/console.py

Quick port of fileservice to the new framework. It's still very much old-style,
though.

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
32
32
 
33
33
import cjson
34
34
 
35
 
from ivle import chat, interpret
 
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')
36
44
 
37
45
class ConsoleError(Exception):
38
46
    """ The console failed in some way. This is bad. """
39
 
    pass
 
47
    def __init__(self, value):
 
48
        self.value = value
 
49
    def __str__(self):
 
50
        return repr(self.value)
40
51
 
41
52
class ConsoleException(Exception):
42
53
    """ The code being exectuted on the console returned an exception. 
43
54
    """
44
 
    pass
 
55
    def __init__(self, value):
 
56
        self.value = value
 
57
    def __str__(self):
 
58
        return repr(self.value)
45
59
 
46
60
class TruncateStringIO(StringIO.StringIO):
47
61
    """ A class that wraps around StringIO and truncates the buffer when the 
108
122
class Console(object):
109
123
    """ Provides a nice python interface to the console
110
124
    """
111
 
    def __init__(self, config, user, jail_path, working_dir):
 
125
    def __init__(self, uid, jail_path, working_dir):
112
126
        """Starts up a console service for user uid, inside chroot jail 
113
127
        jail_path with work directory of working_dir
114
128
        """
115
129
        super(Console, self).__init__()
116
130
 
117
 
        self.config = config
118
 
        self.user = user
 
131
        self.uid = uid
119
132
        self.jail_path = jail_path
120
133
        self.working_dir = working_dir
121
134
 
141
154
 
142
155
        # Create magic
143
156
        # TODO
144
 
        self.magic = hashlib.md5(uuid.uuid4().bytes).hexdigest()
 
157
        self.magic = md5.new(uuid.uuid4().bytes).digest().encode('hex')
145
158
 
146
159
        # Try to find a free port on the server.
147
160
        # Just try some random ports in the range [3000,8000)
152
165
        # is (k / N) ** t (e.g. 3.2*10e-9).
153
166
 
154
167
        tries = 0
155
 
        error = None
156
168
        while tries < 5:
157
169
            self.port = int(random.uniform(3000, 8000))
158
170
 
159
 
            python_console = os.path.join(self.config['paths']['share'],
160
 
                        'services/python-console')
161
 
            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
                ])
162
188
 
163
 
            try:
164
 
                interpret.execute_raw(self.config, self.user, self.jail_path,
165
 
                        self.working_dir, "/usr/bin/python", args)
 
189
            if res == 0:
166
190
                # success
167
 
                break
168
 
            except interpret.ExecutionError, e:
169
 
                tries += 1
170
 
                error = e.message
171
 
 
172
 
        # If we can't start the console after 5 attemps (can't find a free 
173
 
        # port during random probing, syntax errors, segfaults) throw an 
174
 
        # 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.
175
197
        if tries == 5:
176
 
            raise ConsoleError('Unable to start console service: %s'%error)
 
198
            raise ConsoleError("Unable to start console service!")
177
199
 
178
200
    def __chat(self, cmd, args):
179
201
        """ A wrapper around chat.chat to comunicate directly with the 
194
216
            # Couldn't decode the JSON
195
217
            raise ConsoleError(
196
218
                "Could not understand the python console response")
197
 
        except chat.ProtocolError, e:
198
 
            raise ConsoleError(*e.args)
199
219
 
200
220
        return response
201
221
 
280
300
              
281
301
        # Unpickle any exceptions
282
302
        if 'exception' in execute:
283
 
            execute['exception'] = cPickle.loads(execute['exception'])
284
 
        return execute
 
303
            return cPickle.loads(execute['exception'])
 
304
        else:
 
305
            return execute
285
306
 
286
307
 
287
308
    def set_vars(self, variables):