~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
1796.1.2 by William Grant
Replace @named_operation with @read_operation and @write_operation. Allow execution of read operations with a GET rather than a POST.
34
from ivle.webapp.base.rest import JSONRESTView, write_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
1796.1.2 by William Grant
Replace @named_operation with @read_operation and @write_operation. Allow execution of read operations with a GET rather than a POST.
46
    @write_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
        # Start the server
1218 by William Grant
Drop ivle.conf dependency from ivle.webapp.console.service.
51
        jail_path = os.path.join(req.config['paths']['jails']['mounts'],
52
                                 req.user.login)
1773 by David Coles
console: Make sure HOME is set correctly (not always the same as CWD). Also use ivle.interpret.execute_raw rather than duplicating trapoline calling code in ivle.chat
53
        cons = ivle.console.Console(req.config, req.user, jail_path,
54
                working_dir)
1099.1.29 by William Grant
ivle.webapp.console.service: Port www/apps/consoleservice to new framework.
55
56
        # Assemble the key and return it. Yes, it is double-encoded.
57
        return {'key': cjson.encode({"host": cons.host,
58
                                     "port": cons.port,
59
                                     "magic": cons.magic}).encode('hex')}
60
1796.1.2 by William Grant
Replace @named_operation with @read_operation and @write_operation. Allow execution of read operations with a GET rather than a POST.
61
    @write_operation('use')
1332.1.3 by David Coles
Allow sending of cwd along with chat in case console needs to be reset
62
    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.
63
        # The request *should* have the following four fields:
64
        # key: Hex JSON dict of host and port where the console server lives,
65
        # and the secret to use to digitally sign the communication with the
66
        # console server.
67
        # text: Fields to pass along to the console server
68
        # It simply acts as a proxy to the console server
69
70
        try:
71
            keydict = cjson.decode(key.decode('hex'))
72
            host = keydict['host']
73
            port = keydict['port']
74
            magic = keydict['magic']
75
        except KeyError:
76
            raise BadRequest("Invalid console key.")
77
1218 by William Grant
Drop ivle.conf dependency from ivle.webapp.console.service.
78
        jail_path = os.path.join(req.config['paths']['jails']['mounts'],
79
                                 req.user.login)
1332.1.3 by David Coles
Allow sending of cwd along with chat in case console needs to be reset
80
        # Within Jail
81
        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.
82
1243 by William Grant
Decode console input as UTF-8, until JSONRESTView does it for us.
83
        # XXX: JSONRESTView should do this for us.
84
        text = text.decode('utf-8')
85
1099.1.29 by William Grant
ivle.webapp.console.service: Port www/apps/consoleservice to new framework.
86
        msg = {'cmd':kind, 'text':text}
87
        try:
88
            try:
1669 by William Grant
ConsoleService no longer crashes if the console doesn't return a valid netstring.
89
                json_response = ivle.chat.chat(host, port, msg, magic,decode=False)
90
                # 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.
91
                response = cjson.decode(json_response)
1669 by William Grant
ConsoleService no longer crashes if the console doesn't return a valid netstring.
92
            except (cjson.DecodeError, ivle.chat.ProtocolError):
1099.1.29 by William Grant
ivle.webapp.console.service: Port www/apps/consoleservice to new framework.
93
                # Could not decode the reply from the python-console server
94
                response = {"terminate":
1744 by William Grant
Improve console error messages.
95
                    "Communication lost"}
1099.1.29 by William Grant
ivle.webapp.console.service: Port www/apps/consoleservice to new framework.
96
            if "terminate" in response:
1773 by David Coles
console: Make sure HOME is set correctly (not always the same as CWD). Also use ivle.interpret.execute_raw rather than duplicating trapoline calling code in ivle.chat
97
                response = restart_console(req.config, req.user, jail_path,
1275 by William Grant
Kill ivle.console's dependency on ivle.conf.
98
                    working_dir, response["terminate"])
1099.1.29 by William Grant
ivle.webapp.console.service: Port www/apps/consoleservice to new framework.
99
        except socket.error, (enumber, estring):
100
            if enumber == errno.ECONNREFUSED:
101
                # Timeout: Restart the session
1774 by David Coles
console: Fix up crash do to passing unixid rather than User when restarting a console that has timed out
102
                response = restart_console(req.config, req.user, jail_path,
1275 by William Grant
Kill ivle.console's dependency on ivle.conf.
103
                    working_dir,
1744 by William Grant
Improve console error messages.
104
                    "Timed out due to inactivity")
1099.1.29 by William Grant
ivle.webapp.console.service: Port www/apps/consoleservice to new framework.
105
            elif enumber == errno.ECONNRESET:
106
                # Communication issue: Restart the session
1774 by David Coles
console: Fix up crash do to passing unixid rather than User when restarting a console that has timed out
107
                response = restart_console(req.config, req.user, jail_path,
1275 by William Grant
Kill ivle.console's dependency on ivle.conf.
108
                    working_dir,
1744 by William Grant
Improve console error messages.
109
                    "Connection reset")
1099.1.29 by William Grant
ivle.webapp.console.service: Port www/apps/consoleservice to new framework.
110
            else:
111
                # Some other error - probably serious
112
                raise socket.error, (enumber, estring)
113
        return response
216 by mattgiuca
Added new app "consoleservice", ajax back end which runs the console daemon.
114
737 by dcoles
Console: The consoleservice is now able to work out when a console has timed
115
1773 by David Coles
console: Make sure HOME is set correctly (not always the same as CWD). Also use ivle.interpret.execute_raw rather than duplicating trapoline calling code in ivle.chat
116
def restart_console(config, user, jail_path, working_dir, reason):
977 by dcoles
Console: Work on making console more responsive to signals (rather than just
117
    """Tells the client that it must be issued a new console since the old 
118
    console is no longer availible. The client must accept the new key.
119
    Returns the JSON response to be given to the client.
120
    """
121
    # Start a new console server console
1773 by David Coles
console: Make sure HOME is set correctly (not always the same as CWD). Also use ivle.interpret.execute_raw rather than duplicating trapoline calling code in ivle.chat
122
    cons = ivle.console.Console(config, user, jail_path, working_dir)
977 by dcoles
Console: Work on making console more responsive to signals (rather than just
123
124
    # 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
125
    new_key = cjson.encode(
126
        {"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.
127
128
    return {"restart": reason, "key": new_key.encode("hex")}