~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
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
34
import ivle.conf
1099.1.34 by William Grant
Split up ivle.webapp.base.views into ivle.webapp.base.{rest,xhtml}, as it was
35
from ivle.webapp.base.rest import JSONRESTView, named_operation
1099.1.85 by William Grant
Fix some missing error imports in the webapp.
36
from ivle.webapp.errors import BadRequest
1099.1.29 by William Grant
ivle.webapp.console.service: Port www/apps/consoleservice to new framework.
37
38
# XXX: Should be RPC view, with actions in URL?
39
class ConsoleServiceRESTView(JSONRESTView):
40
    '''An RPC interface to a Python console.'''
1099.1.113 by William Grant
Give console and tutorial services security declarations.
41
    def get_permissions(self, user):
42
        if user is not None:
43
            return set(['use'])
44
        else:
45
            return set()
46
47
    @named_operation('use')
1099.1.29 by William Grant
ivle.webapp.console.service: Port www/apps/consoleservice to new framework.
48
    def start(self, req, cwd=''):
49
        working_dir = os.path.join("/home", req.user.login, cwd)
50
51
        uid = req.user.unixid
52
53
        # Start the server
54
        jail_path = os.path.join(ivle.conf.jail_base, req.user.login)
1099.1.32 by William Grant
ivle.webapp.console.service: Clean up.
55
        cons = ivle.console.Console(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')
1099.1.29 by William Grant
ivle.webapp.console.service: Port www/apps/consoleservice to new framework.
63
    def chat(self, req, key, text='', kind="chat"):
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
79
        jail_path = os.path.join(ivle.conf.jail_base, req.user.login)
80
        working_dir = os.path.join("/home", req.user.login)   # Within jail
81
        uid = req.user.unixid
82
83
        msg = {'cmd':kind, 'text':text}
84
        try:
1099.1.32 by William Grant
ivle.webapp.console.service: Clean up.
85
            json_response = ivle.chat.chat(host, port, msg, magic,decode=False)
1099.1.29 by William Grant
ivle.webapp.console.service: Port www/apps/consoleservice to new framework.
86
87
            # Snoop the response from python-console to check that it's valid
88
            try:
89
                response = cjson.decode(json_response)
90
            except cjson.DecodeError:
91
                # Could not decode the reply from the python-console server
92
                response = {"terminate":
93
                    "Communication to console process lost"}
94
            if "terminate" in response:
95
                response = restart_console(uid, jail_path, working_dir,
96
                    response["terminate"])
97
        except socket.error, (enumber, estring):
98
            if enumber == errno.ECONNREFUSED:
99
                # Timeout: Restart the session
100
                response = restart_console(uid, jail_path, working_dir,
101
                    "The IVLE console has timed out due to inactivity")
102
            elif enumber == errno.ECONNRESET:
103
                # Communication issue: Restart the session
104
                response = restart_console(uid, jail_path, working_dir,
105
                    "Connection with the console has been reset")
106
            else:
107
                # Some other error - probably serious
108
                raise socket.error, (enumber, estring)
109
        return response
216 by mattgiuca
Added new app "consoleservice", ajax back end which runs the console daemon.
110
737 by dcoles
Console: The consoleservice is now able to work out when a console has timed
111
977 by dcoles
Console: Work on making console more responsive to signals (rather than just
112
def restart_console(uid, jail_path, working_dir, reason):
113
    """Tells the client that it must be issued a new console since the old 
114
    console is no longer availible. The client must accept the new key.
115
    Returns the JSON response to be given to the client.
116
    """
117
    # Start a new console server console
1099.1.32 by William Grant
ivle.webapp.console.service: Clean up.
118
    cons = ivle.console.Console(uid, jail_path, working_dir)
977 by dcoles
Console: Work on making console more responsive to signals (rather than just
119
120
    # 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
121
    new_key = cjson.encode(
122
        {"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.
123
124
    return {"restart": reason, "key": new_key.encode("hex")}