~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.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.'''
40
    @named_operation
41
    def start(self, req, cwd=''):
42
        working_dir = os.path.join("/home", req.user.login, cwd)
43
44
        uid = req.user.unixid
45
46
        # Start the server
47
        jail_path = os.path.join(ivle.conf.jail_base, req.user.login)
1099.1.32 by William Grant
ivle.webapp.console.service: Clean up.
48
        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.
49
50
        # Assemble the key and return it. Yes, it is double-encoded.
51
        return {'key': cjson.encode({"host": cons.host,
52
                                     "port": cons.port,
53
                                     "magic": cons.magic}).encode('hex')}
54
55
    @named_operation
56
    def chat(self, req, key, text='', kind="chat"):
57
        # The request *should* have the following four fields:
58
        # key: Hex JSON dict of host and port where the console server lives,
59
        # and the secret to use to digitally sign the communication with the
60
        # console server.
61
        # text: Fields to pass along to the console server
62
        # It simply acts as a proxy to the console server
63
64
        try:
65
            keydict = cjson.decode(key.decode('hex'))
66
            host = keydict['host']
67
            port = keydict['port']
68
            magic = keydict['magic']
69
        except KeyError:
70
            raise BadRequest("Invalid console key.")
71
72
        jail_path = os.path.join(ivle.conf.jail_base, req.user.login)
73
        working_dir = os.path.join("/home", req.user.login)   # Within jail
74
        uid = req.user.unixid
75
76
        msg = {'cmd':kind, 'text':text}
77
        try:
1099.1.32 by William Grant
ivle.webapp.console.service: Clean up.
78
            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.
79
80
            # Snoop the response from python-console to check that it's valid
81
            try:
82
                response = cjson.decode(json_response)
83
            except cjson.DecodeError:
84
                # Could not decode the reply from the python-console server
85
                response = {"terminate":
86
                    "Communication to console process lost"}
87
            if "terminate" in response:
88
                response = restart_console(uid, jail_path, working_dir,
89
                    response["terminate"])
90
        except socket.error, (enumber, estring):
91
            if enumber == errno.ECONNREFUSED:
92
                # Timeout: Restart the session
93
                response = restart_console(uid, jail_path, working_dir,
94
                    "The IVLE console has timed out due to inactivity")
95
            elif enumber == errno.ECONNRESET:
96
                # Communication issue: Restart the session
97
                response = restart_console(uid, jail_path, working_dir,
98
                    "Connection with the console has been reset")
99
            else:
100
                # Some other error - probably serious
101
                raise socket.error, (enumber, estring)
102
        return response
216 by mattgiuca
Added new app "consoleservice", ajax back end which runs the console daemon.
103
737 by dcoles
Console: The consoleservice is now able to work out when a console has timed
104
977 by dcoles
Console: Work on making console more responsive to signals (rather than just
105
def restart_console(uid, jail_path, working_dir, reason):
106
    """Tells the client that it must be issued a new console since the old 
107
    console is no longer availible. The client must accept the new key.
108
    Returns the JSON response to be given to the client.
109
    """
110
    # Start a new console server console
1099.1.32 by William Grant
ivle.webapp.console.service: Clean up.
111
    cons = ivle.console.Console(uid, jail_path, working_dir)
977 by dcoles
Console: Work on making console more responsive to signals (rather than just
112
113
    # 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
114
    new_key = cjson.encode(
115
        {"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.
116
117
    return {"restart": reason, "key": new_key.encode("hex")}