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