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

« back to all changes in this revision

Viewing changes to setup.py

  • Committer: Matt Giuca
  • Date: 2010-02-04 03:08:35 UTC
  • Revision ID: matt.giuca@gmail.com-20100204030835-epwx6qs5ippwopl5
Tags: 1.0beta1
Added subversion dumps as part of sample data. ivle-loadsampledata loads these dumps, so the sample data now comes with sample files (requiring a checkout).

Show diffs side-by-side

added added

removed removed

Lines of Context:
21
21
# Date:   12/12/2007
22
22
 
23
23
# This is a command-line application, for use by the administrator.
24
 
# This program configures, builds and installs IVLE in three separate steps.
 
24
# This program is a frontend for the modules in the setup packages that 
 
25
# build and install IVLE in separate steps.
25
26
# It is called with at least one argument, which specifies which operation to
26
27
# take.
27
28
 
28
 
# setup.py conf [args]
29
 
# Configures IVLE with machine-specific details, most notably, various paths.
30
 
# Either prompts the administrator for these details or accepts them as
31
 
# command-line args.
32
 
# Creates www/conf/conf.py and trampoline/conf.h.
33
 
 
34
 
# setup.py build
35
 
# Compiles all files and sets up a jail template in the source directory.
36
 
# Details:
37
 
# Compiles (GCC) trampoline/trampoline.c to trampoline/trampoline.
38
 
# Creates jail/.
39
 
# Creates standard subdirs inside the jail, eg bin, opt, home, tmp.
40
 
# Copies console/ to a location within the jail.
41
 
# Copies OS programs and files to corresponding locations within the jail
42
 
#   (eg. python and Python libs, ld.so, etc).
43
 
# Generates .pyc files for all the IVLE .py files.
44
 
 
45
 
# setup.py listmake (for developer use only)
46
 
# Recurses through the source tree and builds a list of all files which should
47
 
# be copied upon installation. This should be run by the developer before
48
 
# cutting a distribution, and the listfile it generates should be included in
49
 
# the distribution, avoiding the administrator having to run it.
50
 
 
51
 
# setup.py install [--nojail] [--dry|n]
52
 
# (Requires root)
53
 
# Create target install directory ($target).
54
 
# Create $target/bin.
55
 
# Copy trampoline/trampoline to $target/bin.
56
 
# chown and chmod the installed trampoline.
57
 
# Copy www/ to $target.
58
 
# Copy jail/ to jails template directory (unless --nojail specified).
59
 
 
60
 
# TODO: List in help, and handle, args for the conf operation
61
 
 
62
 
import os
63
29
import sys
64
 
import getopt
65
 
import string
66
 
import errno
67
 
 
68
 
# Main function skeleton from Guido van Rossum
69
 
# http://www.artima.com/weblogs/viewpost.jsp?thread=4829
70
 
 
71
 
class Usage(Exception):
72
 
    def __init__(self, msg):
73
 
        self.msg = msg
 
30
import setup.build
 
31
import setup.install
74
32
 
75
33
def main(argv=None):
76
34
    if argv is None:
79
37
    # Print the opening spiel including the GPL notice
80
38
 
81
39
    print """IVLE - Informatics Virtual Learning Environment Setup
82
 
Copyright (C) 2007-2008 The University of Melbourne
 
40
Copyright (C) 2007-2009 The University of Melbourne
83
41
IVLE comes with ABSOLUTELY NO WARRANTY.
84
42
This is free software, and you are welcome to redistribute it
85
43
under certain conditions. See LICENSE.txt for details.
95
53
        help([])
96
54
        return 1
97
55
 
 
56
    oper_func = call_operator(operation)
 
57
    return oper_func(argv[2:])
 
58
 
 
59
def help(args):
 
60
    if len(args)!=1:
 
61
        print """Usage: python setup.py operation [options]
 
62
Operation can be:
 
63
    help [operation]
 
64
    build
 
65
    install
 
66
 
 
67
    For help and options for a specific operation use 'help [operation]'."""
 
68
    else:
 
69
        operator = args[0]
 
70
        oper_func = call_operator(operator)
 
71
        oper_func(['operator','--help'])
 
72
 
 
73
def call_operator(operation):
98
74
    # Call the requested operation's function
99
75
    try:
100
 
        return {
 
76
        oper_func = {
101
77
            'help' : help,
102
 
            'conf' : conf,
103
 
            'build' : build,
104
 
            'listmake' : listmake,
105
 
            'install' : install,
106
 
        }[operation](argv[2:])
 
78
            'build' : setup.build.build,
 
79
            'install' : setup.install.install,
 
80
        }[operation]
107
81
    except KeyError:
108
82
        print >>sys.stderr, (
109
83
            """Invalid operation '%s'. Try python setup.py help."""
110
84
            % operation)
111
 
 
112
 
    try:
113
 
        try:
114
 
            opts, args = getopt.getopt(argv[1:], "h", ["help"])
115
 
        except getopt.error, msg:
116
 
            raise Usage(msg)
117
 
        # more code, unchanged
118
 
    except Usage, err:
119
 
        print >>sys.stderr, err.msg
120
 
        print >>sys.stderr, "for help use --help"
121
 
        return 2
122
 
 
123
 
# Operation functions
124
 
 
125
 
def help(args):
126
 
    if args == []:
127
 
        print """Usage: python setup.py operation [args]
128
 
Operation (and args) can be:
129
 
    help [operation]
130
 
    conf [args]
131
 
    build
132
 
    install [--nojail] [-n|--dry]
133
 
"""
134
 
        return 1
135
 
    elif len(args) != 1:
136
 
        print """Usage: python setup.py help [operation]"""
137
 
        return 2
138
 
    else:
139
 
        operation = args[0]
140
 
 
141
 
    if operation == 'help':
142
 
        print """python setup.py help [operation]
143
 
Prints the usage message or detailed help on an operation, then exits."""
144
 
    elif operation == 'conf':
145
 
        print """python setup.py conf [args]
146
 
Configures IVLE with machine-specific details, most notably, various paths.
147
 
Either prompts the administrator for these details or accepts them as
148
 
command-line args.
149
 
Creates www/conf/conf.py and trampoline/conf.h.
150
 
Args are:
151
 
"""
152
 
    elif operation == 'build':
153
 
        print """python setup.py build
154
 
Compiles all files and sets up a jail template in the source directory.
155
 
Details:
156
 
Compiles (GCC) trampoline/trampoline.c to trampoline/trampoline.
157
 
Creates jail/.
158
 
Creates standard subdirs inside the jail, eg bin, opt, home, tmp.
159
 
Copies console/ to a location within the jail.
160
 
Copies OS programs and files to corresponding locations within the jail
161
 
  (eg. python and Python libs, ld.so, etc).
162
 
Generates .pyc files for all the IVLE .py files."""
163
 
    elif operation == 'listmake':
164
 
        print """python setup.py listmake
165
 
(For developer use only)
166
 
Recurses through the source tree and builds a list of all files which should
167
 
be copied upon installation. This should be run by the developer before
168
 
cutting a distribution, and the listfile it generates should be included in
169
 
the distribution, avoiding the administrator having to run it."""
170
 
    elif operation == 'install':
171
 
        print """sudo python setup.py install [--nojail] [--dry|-n]
172
 
(Requires root)
173
 
Create target install directory ($target).
174
 
Create $target/bin.
175
 
Copy trampoline/trampoline to $target/bin.
176
 
chown and chmod the installed trampoline.
177
 
Copy www/ to $target.
178
 
Copy jail/ to jails template directory (unless --nojail specified).
179
 
 
180
 
--nojail    Do not copy the jail.
181
 
--dry | -n  Print out the actions but don't do anything."""
182
 
    else:
183
 
        print >>sys.stderr, (
184
 
            """Invalid operation '%s'. Try python setup.py help."""
185
 
            % operation)
186
 
    return 1
187
 
 
188
 
def conf(args):
189
 
    # Set up some variables
190
 
 
191
 
    cwd = os.getcwd()
192
 
    # the files that will be created/overwritten
193
 
    conffile = os.path.join(cwd, "www/conf/conf.py")
194
 
    conf_hfile = os.path.join(cwd, "trampoline/conf.h")
195
 
 
196
 
    # Fixed config options that we don't ask the admin
197
 
 
198
 
    default_app = "dummy"
199
 
 
200
 
    print """This tool will create the following files:
201
 
    %s
202
 
    %s
203
 
prompting you for details about your configuration. The file will be
204
 
overwritten if it already exists. It will *not* install or deploy IVLE.
205
 
 
206
 
Please hit Ctrl+C now if you do not wish to do this.
207
 
""" % (conffile, conf_hfile)
208
 
 
209
 
    # Get information from the administrator
210
 
    # If EOF is encountered at any time during the questioning, just exit
211
 
    # silently
212
 
 
213
 
    root_dir = query_user(
214
 
    """Root directory where IVLE is located (in URL space):
215
 
    (eg. "/" or "/ivle")""")
216
 
    ivle_install_dir = query_user(
217
 
    'Root directory where IVLE is located (on the local file system):\n'
218
 
    '(eg. "/home/informatics/ivle")')
219
 
    jail_base = query_user(
220
 
    """Root directory where user files are stored (on the local file system):
221
 
    (eg. "/home/informatics/jails")""")
222
 
    allowed_uid = query_user(
223
 
    """UID of the web server process which will run IVLE.
224
 
Only this user may execute the trampoline. You can configure multiple users
225
 
by manually editing conf.h.
226
 
    (eg. "1002")""")
227
 
 
228
 
    # Error handling on input values
229
 
 
230
 
    try:
231
 
        allowed_uid = int(allowed_uid)
232
 
    except ValueError:
233
 
        print >>sys.stderr, "Invalid UID (%s)." % allowed_uid
234
 
        return 1
235
 
 
236
 
    # Write www/conf/conf.py
237
 
 
238
 
    try:
239
 
        conf = open(conffile, "w")
240
 
 
241
 
        conf.write("""# IVLE Configuration File
242
 
# conf.py
243
 
# Miscellaneous application settings
244
 
 
245
 
 
246
 
# In URL space, where in the site is IVLE located. (All URLs will be prefixed
247
 
# with this).
248
 
# eg. "/" or "/ivle".
249
 
root_dir = "%s"
250
 
 
251
 
# In the local file system, where IVLE is actually installed.
252
 
# This directory should contain the "www" and "bin" directories.
253
 
ivle_install_dir = "%s"
254
 
 
255
 
# In the local file system, where are the student/user file spaces located.
256
 
# The user jails are expected to be located immediately in subdirectories of
257
 
# this location.
258
 
jail_base = "%s"
259
 
 
260
 
# Which application to load by default (if the user navigates to the top level
261
 
# of the site). This is the app's URL name.
262
 
# Note that if this app requires authentication, the user will first be
263
 
# presented with the login screen.
264
 
default_app = "%s"
265
 
""" % (root_dir, ivle_install_dir, jail_base, default_app))
266
 
 
267
 
        conf.close()
268
 
    except IOError, (errno, strerror):
269
 
        print "IO error(%s): %s" % (errno, strerror)
270
 
        sys.exit(1)
271
 
 
272
 
    print "Successfully wrote www/conf/conf.py"
273
 
 
274
 
    # Write trampoline/conf.h
275
 
 
276
 
    try:
277
 
        conf = open(conf_hfile, "w")
278
 
 
279
 
        conf.write("""/* IVLE Configuration File
280
 
 * conf.h
281
 
 * Administrator settings required by trampoline.
282
 
 * Note: trampoline will have to be rebuilt in order for changes to this file
283
 
 * to take effect.
284
 
 */
285
 
 
286
 
/* In the local file system, where are the jails located.
287
 
 * The trampoline does not allow the creation of a jail anywhere besides
288
 
 * jail_base or a subdirectory of jail_base.
289
 
 */
290
 
static const char* jail_base = "%s";
291
 
 
292
 
/* Which user IDs are allowed to run the trampoline.
293
 
 * This list should be limited to the web server user.
294
 
 * (Note that root is an implicit member of this list).
295
 
 */
296
 
static const int allowed_uids[] = { %d };
297
 
""" % (jail_base, allowed_uid))
298
 
 
299
 
        conf.close()
300
 
    except IOError, (errno, strerror):
301
 
        print "IO error(%s): %s" % (errno, strerror)
302
 
        sys.exit(1)
303
 
 
304
 
    print "Successfully wrote trampoline/conf.h"
305
 
 
306
 
    print
307
 
    print "You may modify the configuration at any time by editing"
308
 
    print conffile
309
 
    print conf_hfile
310
 
    print
311
 
    return 0
312
 
 
313
 
def build(args):
314
 
    dry = False     # Set to True later if --dry
315
 
 
316
 
    # Compile the trampoline
317
 
    action_runprog('gcc', ['-Wall', '-o', 'trampoline/trampoline',
318
 
        'trampoline/trampoline.c'], dry)
319
 
 
320
 
    # Create the jail and its subdirectories
321
 
    action_mkdir('jail')
322
 
    action_mkdir('jail/bin')
323
 
    action_mkdir('jail/lib')
324
 
    action_mkdir('jail/usr')
325
 
    action_mkdir('jail/usr/bin')
326
 
    action_mkdir('jail/usr/lib')
327
 
    action_mkdir('jail/opt')
328
 
    action_mkdir('jail/home')
329
 
    action_mkdir('jail/tmp')
330
 
 
331
 
    # TODO: Copy console into the jail
332
 
    # TODO: Copy operating system files into the jail
333
 
    # TODO: Compile .py files into .pyc files
334
 
 
335
 
    return 0
336
 
 
337
 
def listmake(args):
338
 
    print "Listmake"
339
 
    return 0
340
 
 
341
 
def install(args):
342
 
    print "Install"
343
 
    return 0
344
 
 
345
 
# The actions call Python os functions but print actions and handle dryness.
346
 
# May still throw os exceptions if errors occur.
347
 
 
348
 
class RunError:
349
 
    """Represents an error when running a program (nonzero return)."""
350
 
    def __init__(self, prog, retcode):
351
 
        self.prog = prog
352
 
        self.retcode = retcode
353
 
    def __str__(self):
354
 
        return str(self.prog) + " returned " + repr(self.retcode)
355
 
 
356
 
def action_runprog(prog, args, dry):
357
 
    """Runs a unix program. Searches in $PATH. Synchronous (waits for the
358
 
    program to return). Runs in the current environment. First prints the
359
 
    action as a "bash" line.
360
 
 
361
 
    Throws a RunError with a retcode of the return value of the program,
362
 
    if the program did not return 0.
363
 
 
364
 
    prog: String. Name of the program. (No path required, if in $PATH).
365
 
    args: [String]. Arguments to the program.
366
 
    dry: Bool. If True, prints but does not execute.
367
 
    """
368
 
    print prog, string.join(args, ' ')
369
 
    if not dry:
370
 
        ret = os.spawnvp(os.P_WAIT, prog, args)
371
 
        if ret != 0:
372
 
            raise RunError(prog, ret)
373
 
 
374
 
def action_mkdir(path):
375
 
    """Calls mkdir. Silently ignored if the directory already exists."""
376
 
    print "mkdir", path
377
 
    try:
378
 
        os.mkdir(path)
379
 
    except OSError, (err, msg):
380
 
        if err != errno.EEXIST:
381
 
            raise
382
 
 
383
 
def query_user(prompt):
384
 
    """Prompts the user for a string, which is read from a line of stdin.
385
 
    Exits silently if EOF is encountered. Returns the string, with spaces
386
 
    removed from the beginning and end.
387
 
    """
388
 
    sys.stdout.write(prompt)
389
 
    sys.stdout.write("\n>")
390
 
    try:
391
 
        val = sys.stdin.readline()
392
 
    except KeyboardInterrupt:
393
 
        # Ctrl+C
394
 
        sys.stdout.write("\n")
395
 
        sys.exit(1)
396
 
    sys.stdout.write("\n")
397
 
    if val == '': sys.exit(1)
398
 
    return val.strip()
 
85
        sys.exit(1)
 
86
    return oper_func
399
87
 
400
88
if __name__ == "__main__":
401
89
    sys.exit(main())
 
90