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

1099.1.29 by William Grant
ivle.webapp.console.service: Port www/apps/consoleservice to new framework.
1
# IVLE - Informatics Virtual Learning Environment
2
# Copyright (C) 2007-2009 The University of Melbourne
216 by mattgiuca
Added new app "consoleservice", ajax back end which runs the console daemon.
3
#
4
# This program is free software; you can redistribute it and/or modify
5
# it under the terms of the GNU General Public License as published by
6
# the Free Software Foundation; either version 2 of the License, or
7
# (at your option) any later version.
8
#
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU General Public License for more details.
13
#
14
# You should have received a copy of the GNU General Public License
15
# along with this program; if not, write to the Free Software
16
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17
1099.1.29 by William Grant
ivle.webapp.console.service: Port www/apps/consoleservice to new framework.
18
# Author: Matt Giuca, Tom Conway, Will Grant
19
20
'''Python console RPC service.
21
22
Provides an HTTP RPC interface to a Python console process.
23
24
'''
216 by mattgiuca
Added new app "consoleservice", ajax back end which runs the console daemon.
25
26
import os
352 by drtomc
Changed console so it no longer uses HTTP, just sends JSON over a normal socket.
27
import socket
216 by mattgiuca
Added new app "consoleservice", ajax back end which runs the console daemon.
28
29
import cjson
1099.1.29 by William Grant
ivle.webapp.console.service: Port www/apps/consoleservice to new framework.
30
import errno
216 by mattgiuca
Added new app "consoleservice", ajax back end which runs the console daemon.
31
1099.1.32 by William Grant
ivle.webapp.console.service: Clean up.
32
import ivle.console
33
import ivle.chat
1099.1.34 by William Grant
Split up ivle.webapp.base.views into ivle.webapp.base.{rest,xhtml}, as it was
34
from ivle.webapp.base.rest import JSONRESTView, named_operation
1099.1.85 by William Grant
Fix some missing error imports in the webapp.
35
from ivle.webapp.errors import BadRequest
1099.1.29 by William Grant
ivle.webapp.console.service: Port www/apps/consoleservice to new framework.
36
37
# XXX: Should be RPC view, with actions in URL?
38
class ConsoleServiceRESTView(JSONRESTView):
39
    '''An RPC interface to a Python console.'''
1544 by Matt Giuca
Added an argument 'config' to every single get_permissions method throughout the program. All calls to get_permissions pass a config. This is to allow per-site policy configurations on permissions.
40
    def get_permissions(self, user, config):
1099.1.113 by William Grant
Give console and tutorial services security declarations.
41
        if user is not None:
42
            return set(['use'])
43
        else:
44
            return set()
45
46
    @named_operation('use')
1099.1.29 by William Grant
ivle.webapp.console.service: Port www/apps/consoleservice to new framework.
47
    def start(self, req, cwd=''):
48
        working_dir = os.path.join("/home", req.user.login, cwd)
49
50
        uid = req.user.unixid
51
52
        # Start the server
1218 by William Grant
Drop ivle.conf dependency from ivle.webapp.console.service.
53
        jail_path = os.path.join(req.config['paths']['jails']['mounts'],
54
                                 req.user.login)
1275 by William Grant
Kill ivle.console's dependency on ivle.conf.
55
        cons = ivle.console.Console(req.config, uid, jail_path, working_dir)
1099.1.29 by William Grant
ivle.webapp.console.service: Port www/apps/consoleservice to new framework.
56
57
        # Assemble the key and return it. Yes, it is double-encoded.
58
        return {'key': cjson.encode({"host": cons.host,
59
                                     "port": cons.port,
60
                                     "magic": cons.magic}).encode('hex')}
61
1099.1.113 by William Grant
Give console and tutorial services security declarations.
62
    @named_operation('use')
1332.1.3 by David Coles
Allow sending of cwd along with chat in case console needs to be reset
63
    def chat(self, req, key, text='', cwd='', kind="chat"):
1099.1.29 by William Grant
ivle.webapp.console.service: Port www/apps/consoleservice to new framework.
64
        # The request *should* have the following four fields:
65
        # key: Hex JSON dict of host and port where the console server lives,
66
        # and the secret to use to digitally sign the communication with the
67
        # console server.
68
        # text: Fields to pass along to the console server
69
        # It simply acts as a proxy to the console server
70
71
        try:
72
            keydict = cjson.decode(key.decode('hex'))
73
            host = keydict['host']
74
            port = keydict['port']
75
            magic = keydict['magic']
76
        except KeyError:
77
            raise BadRequest("Invalid console key.")
78
1218 by William Grant
Drop ivle.conf dependency from ivle.webapp.console.service.
79
        jail_path = os.path.join(req.config['paths']['jails']['mounts'],
80
                                 req.user.login)
1332.1.3 by David Coles
Allow sending of cwd along with chat in case console needs to be reset
81
        # Within Jail
82
        working_dir = os.path.join("/home", req.user.login, cwd)
1099.1.29 by William Grant
ivle.webapp.console.service: Port www/apps/consoleservice to new framework.
83
        uid = req.user.unixid
84
1243 by William Grant
Decode console input as UTF-8, until JSONRESTView does it for us.
85
        # XXX: JSONRESTView should do this for us.
86
        text = text.decode('utf-8')
87
1099.1.29 by William Grant
ivle.webapp.console.service: Port www/apps/consoleservice to new framework.
88
        msg = {'cmd':kind, 'text':text}
89
        try:
90
            try:
1669 by William Grant
ConsoleService no longer crashes if the console doesn't return a valid netstring.
91
                json_response = ivle.chat.chat(host, port, msg, magic,decode=False)
92
                # Snoop the response from python-console to check that it's valid
1099.1.29 by William Grant
ivle.webapp.console.service: Port www/apps/consoleservice to new framework.
93
                response = cjson.decode(json_response)
1669 by William Grant
ConsoleService no longer crashes if the console doesn't return a valid netstring.
94
            except (cjson.DecodeError, ivle.chat.ProtocolError):
1099.1.29 by William Grant
ivle.webapp.console.service: Port www/apps/consoleservice to new framework.
95
                # Could not decode the reply from the python-console server
96
                response = {"terminate":
97
                    "Communication to console process lost"}
98
            if "terminate" in response:
1275 by William Grant
Kill ivle.console's dependency on ivle.conf.
99
                response = restart_console(req.config, uid, jail_path,
100
                    working_dir, response["terminate"])
1099.1.29 by William Grant
ivle.webapp.console.service: Port www/apps/consoleservice to new framework.
101
        except socket.error, (enumber, estring):
102
            if enumber == errno.ECONNREFUSED:
103
                # Timeout: Restart the session
1275 by William Grant
Kill ivle.console's dependency on ivle.conf.
104
                response = restart_console(req.config, uid, jail_path,
105
                    working_dir,
1099.1.29 by William Grant
ivle.webapp.console.service: Port www/apps/consoleservice to new framework.
106
                    "The IVLE console has timed out due to inactivity")
107
            elif enumber == errno.ECONNRESET:
108
                # Communication issue: Restart the session
1275 by William Grant
Kill ivle.console's dependency on ivle.conf.
109
                response = restart_console(req.config, uid, jail_path,
110
                    working_dir,
1099.1.29 by William Grant
ivle.webapp.console.service: Port www/apps/consoleservice to new framework.
111
                    "Connection with the console has been reset")
112
            else:
113
                # Some other error - probably serious
114
                raise socket.error, (enumber, estring)
115
        return response
216 by mattgiuca
Added new app "consoleservice", ajax back end which runs the console daemon.
116
737 by dcoles
Console: The consoleservice is now able to work out when a console has timed
117
1275 by William Grant
Kill ivle.console's dependency on ivle.conf.
118
def restart_console(config, uid, jail_path, working_dir, reason):
977 by dcoles
Console: Work on making console more responsive to signals (rather than just
119
    """Tells the client that it must be issued a new console since the old 
120
    console is no longer availible. The client must accept the new key.
121
    Returns the JSON response to be given to the client.
122
    """
123
    # Start a new console server console
1275 by William Grant
Kill ivle.console's dependency on ivle.conf.
124
    cons = ivle.console.Console(config, uid, jail_path, working_dir)
977 by dcoles
Console: Work on making console more responsive to signals (rather than just
125
126
    # Make a JSON object to tell the browser to restart its console client
1017 by dcoles
Console: Refactored a lot of the console stuff into a class to make calls to
127
    new_key = cjson.encode(
128
        {"host": cons.host, "port": cons.port, "magic": cons.magic})
1099.1.30 by William Grant
ivle.webapp.console.service#restart_console: Don't double-JSON.
129
130
    return {"restart": reason, "key": new_key.encode("hex")}