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

« back to all changes in this revision

Viewing changes to setup.py

  • Committer: stevenbird
  • Date: 2008-01-31 23:40:25 UTC
  • Revision ID: svn-v3-trunk0:2b9c9e99-6f39-0410-b283-7f802c844ae2:trunk:357
fixed syntax error

Show diffs side-by-side

added added

removed removed

Lines of Context:
35
35
# Configures IVLE with machine-specific details, most notably, various paths.
36
36
# Either prompts the administrator for these details or accepts them as
37
37
# command-line args.
38
 
# Creates lib/conf/conf.py and trampoline/conf.h.
 
38
# Creates www/conf/conf.py and trampoline/conf.h.
39
39
 
40
40
# setup.py build
41
41
# Compiles all files and sets up a jail template in the source directory.
67
67
import mimetypes
68
68
import compileall
69
69
import getopt
70
 
import hashlib
71
 
import uuid
72
70
 
73
71
# Import modules from the website is tricky since they're in the www
74
72
# directory.
75
 
sys.path.append(os.path.join(os.getcwd(), 'lib'))
 
73
sys.path.append(os.path.join(os.getcwd(), 'www'))
76
74
import conf
77
75
import common.makeuser
78
76
 
102
100
    '/bin/echo',
103
101
    # Needed by python
104
102
    '/usr/bin/python%s' % PYTHON_VERSION,
105
 
    # Needed by fileservice
106
 
    '/lib/libcom_err.so.2',
107
 
    '/lib/libcrypt.so.1',
108
 
    '/lib/libkeyutils.so.1',
109
 
    '/lib/libresolv.so.2',
110
 
    '/lib/librt.so.1',
111
 
    '/lib/libuuid.so.1',
112
 
    '/usr/lib/libapr-1.so.0',
113
 
    '/usr/lib/libaprutil-1.so.0',
114
 
    '/usr/lib/libdb-4.4.so',
115
 
    '/usr/lib/libexpat.so.1',
116
 
    '/usr/lib/libgcrypt.so.11',
117
 
    '/usr/lib/libgnutls.so.13',
118
 
    '/usr/lib/libgpg-error.so.0',
119
 
    '/usr/lib/libgssapi_krb5.so.2',
120
 
    '/usr/lib/libk5crypto.so.3',
121
 
    '/usr/lib/libkrb5.so.3',
122
 
    '/usr/lib/libkrb5support.so.0',
123
 
    '/usr/lib/liblber.so.2',
124
 
    '/usr/lib/libldap_r.so.2',
125
 
    '/usr/lib/libneon.so.26',
126
 
    '/usr/lib/libpq.so.5',
127
 
    '/usr/lib/libsasl2.so.2',
128
 
    '/usr/lib/libsqlite3.so.0',
129
 
    '/usr/lib/libsvn_client-1.so.1',
130
 
    '/usr/lib/libsvn_delta-1.so.1',
131
 
    '/usr/lib/libsvn_diff-1.so.1',
132
 
    '/usr/lib/libsvn_fs-1.so.1',
133
 
    '/usr/lib/libsvn_fs_base-1.so.1',
134
 
    '/usr/lib/libsvn_fs_fs-1.so.1',
135
 
    '/usr/lib/libsvn_ra-1.so.1',
136
 
    '/usr/lib/libsvn_ra_dav-1.so.1',
137
 
    '/usr/lib/libsvn_ra_local-1.so.1',
138
 
    '/usr/lib/libsvn_ra_svn-1.so.1',
139
 
    '/usr/lib/libsvn_repos-1.so.1',
140
 
    '/usr/lib/libsvn_subr-1.so.1',
141
 
    '/usr/lib/libsvn_wc-1.so.1',
142
 
    '/usr/lib/libtasn1.so.3',
143
 
    '/usr/lib/libxml2.so.2',
144
103
    # Needed by matplotlib
145
104
    '/usr/lib/i686/cmov/libssl.so.0.9.8',
146
105
    '/usr/lib/i686/cmov/libcrypto.so.0.9.8',
161
120
    '/usr/lib/libXdmcp.so.6',
162
121
    '/lib/libgcc_s.so.1',
163
122
    '/etc/matplotlibrc',
164
 
    # Needed for resolv
165
 
    '/lib/libnss_dns.so.2',
166
 
    '/lib/libnss_mdns4_minimal.so.2',
167
 
    '/etc/hosts',
168
 
    '/etc/resolv.conf',
169
 
    #'/etc/hosts.conf',
170
 
    #'/etc/hostname',
171
 
    '/etc/nsswitch.conf',
172
 
    '/lib/libnss_files.so.2',
173
123
]
174
124
# Symlinks to make within the jail. Src mapped to dst.
175
125
JAIL_LINKS = {
181
131
        'jail/usr/lib/python%s' % PYTHON_VERSION,
182
132
    '/usr/share/matplotlib': 'jail/usr/share/matplotlib',
183
133
    '/etc/ld.so.conf.d': 'jail/etc/ld.so.conf.d',
184
 
    '/usr/share/nltk': 'jail/usr/share/nltk',
185
134
}
186
135
 
187
 
class ConfigOption:
188
 
    """A configuration option; one of the things written to conf.py."""
189
 
    def __init__(self, option_name, default, prompt, comment):
190
 
        """Creates a configuration option.
191
 
        option_name: Name of the variable in conf.py. Also name of the
192
 
            command-line argument to setup.py conf.
193
 
        default: Default value for this variable.
194
 
        prompt: (Short) string presented during the interactive prompt in
195
 
            setup.py conf.
196
 
        comment: (Long) comment string stored in conf.py. Each line of this
197
 
            string should begin with a '#'.
198
 
        """
199
 
        self.option_name = option_name
200
 
        self.default = default
201
 
        self.prompt = prompt
202
 
        self.comment = comment
203
 
 
204
 
# Configuration options, defaults and descriptions
205
 
config_options = []
206
 
config_options.append(ConfigOption("root_dir", "/",
207
 
    """Root directory where IVLE is located (in URL space):""",
208
 
    """
209
 
# In URL space, where in the site is IVLE located. (All URLs will be prefixed
210
 
# with this).
211
 
# eg. "/" or "/ivle"."""))
212
 
config_options.append(ConfigOption("ivle_install_dir", "/opt/ivle",
213
 
    'Root directory where IVLE will be installed (on the local file '
214
 
    'system):',
215
 
    """
216
 
# In the local file system, where IVLE is actually installed.
217
 
# This directory should contain the "www" and "bin" directories."""))
218
 
config_options.append(ConfigOption("jail_base", "/home/informatics/jails",
219
 
    """Location of Directories
220
 
=======================
221
 
Root directory where the jails (containing user files) are stored
222
 
(on the local file system):""",
223
 
    """
224
 
# In the local file system, where are the student/user file spaces located.
225
 
# The user jails are expected to be located immediately in subdirectories of
226
 
# this location."""))
227
 
config_options.append(ConfigOption("subjects_base",
228
 
    "/home/informatics/subjects",
229
 
    """Root directory where the subject directories (containing worksheets
230
 
and other per-subject files) are stored (on the local file system):""",
231
 
    """
232
 
# In the local file system, where are the per-subject file spaces located.
233
 
# The individual subject directories are expected to be located immediately
234
 
# in subdirectories of this location."""))
235
 
config_options.append(ConfigOption("exercises_base",
236
 
    "/home/informatics/exercises",
237
 
    """Root directory where the exercise directories (containing
238
 
subject-independent exercise sheets) are stored (on the local file
239
 
system):""",
240
 
    """
241
 
# In the local file system, where are the subject-independent exercise sheet
242
 
# file spaces located."""))
243
 
config_options.append(ConfigOption("tos_path",
244
 
    "/home/informatics/tos.html",
245
 
    """Location where the Terms of Service document is stored (on the local
246
 
    file system):""",
247
 
    """
248
 
# In the local file system, where is the Terms of Service document located."""))
249
 
config_options.append(ConfigOption("motd_path",
250
 
    "/home/informatics/motd.html",
251
 
    """Location where the Message of the Day document is stored (on the local
252
 
    file system):""",
253
 
    """
254
 
# In the local file system, where is the Message of the Day document
255
 
# located. This is an HTML file (just the body fragment), which will
256
 
# be displayed on the login page. It is optional."""))
257
 
config_options.append(ConfigOption("public_host", "public.localhost",
258
 
    """Hostname which will cause the server to go into "public mode",
259
 
providing login-free access to student's published work:""",
260
 
    """
261
 
# The server goes into "public mode" if the browser sends a request with this
262
 
# host. This is for security reasons - we only serve public student files on a
263
 
# separate domain to the main IVLE site.
264
 
# Public mode does not use cookies, and serves only public content.
265
 
# Private mode (normal mode) requires login, and only serves files relevant to
266
 
# the logged-in user."""))
267
 
config_options.append(ConfigOption("allowed_uids", "33",
268
 
    """UID of the web server process which will run IVLE.
269
 
Only this user may execute the trampoline. May specify multiple users as
270
 
a comma-separated list.
271
 
    (eg. "1002,78")""",
272
 
    """
273
 
# The User-ID of the web server process which will run IVLE, and any other
274
 
# users who are allowed to run the trampoline. This is stores as a string of
275
 
# comma-separated integers, simply because it is not used within Python, only
276
 
# used by the setup program to write to conf.h (see setup.py config)."""))
277
 
config_options.append(ConfigOption("db_host", "localhost",
278
 
    """PostgreSQL Database config
279
 
==========================
280
 
Hostname of the DB server:""",
281
 
    """
282
 
### PostgreSQL Database config ###
283
 
# Database server hostname"""))
284
 
config_options.append(ConfigOption("db_port", "5432",
285
 
    """Port of the DB server:""",
286
 
    """
287
 
# Database server port"""))
288
 
config_options.append(ConfigOption("db_dbname", "ivle",
289
 
    """Database name:""",
290
 
    """
291
 
# Database name"""))
292
 
config_options.append(ConfigOption("db_forumdbname", "ivle_forum",
293
 
    """Forum Database name:""",
294
 
    """
295
 
# Forum Database name"""))
296
 
config_options.append(ConfigOption("db_user", "postgres",
297
 
    """Username for DB server login:""",
298
 
    """
299
 
# Database username"""))
300
 
config_options.append(ConfigOption("db_password", "",
301
 
    """Password for DB server login:
302
 
    (Caution: This password is stored in plaintext in lib/conf/conf.py)""",
303
 
    """
304
 
# Database password"""))
305
 
config_options.append(ConfigOption("auth_modules", "ldap_auth",
306
 
    """Authentication config
307
 
=====================
308
 
Comma-separated list of authentication modules. Only "ldap" is available
309
 
by default.""",
310
 
    """
311
 
# Comma-separated list of authentication modules.
312
 
# These refer to importable Python modules in the www/auth directory.
313
 
# Modules "ldap" and "guest" are available in the source tree, but
314
 
# other modules may be plugged in to auth against organisation-specific
315
 
# auth backends."""))
316
 
config_options.append(ConfigOption("ldap_url", "ldaps://www.example.com",
317
 
    """(LDAP options are only relevant if "ldap" is included in the list of
318
 
auth modules).
319
 
URL for LDAP authentication server:""",
320
 
    """
321
 
# URL for LDAP authentication server"""))
322
 
config_options.append(ConfigOption("ldap_format_string",
323
 
    "uid=%s,ou=users,o=example",
324
 
    """Format string for LDAP auth request:
325
 
    (Must contain a single "%s" for the user's login name)""",
326
 
    """
327
 
# Format string for LDAP auth request
328
 
# (Must contain a single "%s" for the user's login name)"""))
329
 
config_options.append(ConfigOption("svn_addr", "http://svn.localhost/",
330
 
    """Subversion config
331
 
=================
332
 
The base url for accessing subversion repositories:""",
333
 
    """
334
 
# The base url for accessing subversion repositories."""))
335
 
config_options.append(ConfigOption("svn_conf", "/opt/ivle/svn/svn.conf",
336
 
    """The location of the subversion configuration file used by apache
337
 
to host the user repositories:""",
338
 
    """
339
 
# The location of the subversion configuration file used by
340
 
# apache to host the user repositories."""))
341
 
config_options.append(ConfigOption("svn_repo_path", "/home/informatics/repositories",
342
 
    """The root directory for the subversion repositories:""",
343
 
    """
344
 
# The root directory for the subversion repositories."""))
345
 
config_options.append(ConfigOption("svn_auth_ivle", "/opt/ivle/svn/ivle.auth",
346
 
    """The location of the password file used to authenticate users
347
 
of the subversion repository from the ivle server:""",
348
 
    """
349
 
# The location of the password file used to authenticate users
350
 
# of the subversion repository from the ivle server."""))
351
 
config_options.append(ConfigOption("svn_auth_local", "/opt/ivle/svn/local.auth",
352
 
    """The location of the password file used to authenticate local users
353
 
of the subversion repository:""",
354
 
    """
355
 
# The location of the password file used to authenticate local users
356
 
# of the subversion repository."""))
357
 
config_options.append(ConfigOption("usrmgt_host", "localhost",
358
 
    """User Management Server config
359
 
============================
360
 
The hostname where the usrmgt-server runs:""",
361
 
    """
362
 
# The hostname where the usrmgt-server runs."""))
363
 
config_options.append(ConfigOption("usrmgt_port", "2178",
364
 
    """The port where the usrmgt-server runs:""",
365
 
    """
366
 
# The port where the usrmgt-server runs."""))
367
 
config_options.append(ConfigOption("usrmgt_magic", "",
368
 
    """The password for the usrmgt-server:""",
369
 
    """
370
 
# The password for the usrmgt-server."""))
371
 
 
372
136
# Try importing existing conf, but if we can't just set up defaults
373
137
# The reason for this is that these settings are used by other phases
374
138
# of setup besides conf, so we need to know them.
375
139
# Also this allows you to hit Return to accept the existing value.
376
140
try:
377
 
    confmodule = __import__("lib/conf/conf")
378
 
    for opt in config_options:
379
 
        try:
380
 
            globals()[opt.option_name] = confmodule.__dict__[opt.option_name]
381
 
        except:
382
 
            globals()[opt.option_name] = opt.default
 
141
    confmodule = __import__("www/conf/conf")
 
142
    try:
 
143
        root_dir = confmodule.root_dir
 
144
    except:
 
145
        root_dir = "/ivle"
 
146
    try:
 
147
        ivle_install_dir = confmodule.ivle_install_dir
 
148
    except:
 
149
        ivle_install_dir = "/opt/ivle"
 
150
    try:
 
151
        public_host = confmodule.public_host
 
152
    except:
 
153
        public_host = "public.localhost"
 
154
    try:
 
155
        jail_base = confmodule.jail_base
 
156
    except:
 
157
        jail_base = "/home/informatics/jails"
 
158
    try:
 
159
        subjects_base = confmodule.subjects_base
 
160
    except:
 
161
        subjects_base = "/home/informatics/subjects"
383
162
except ImportError:
384
163
    # Just set reasonable defaults
385
 
    for opt in config_options:
386
 
        globals()[opt.option_name] = opt.default
 
164
    root_dir = "/ivle"
 
165
    ivle_install_dir = "/opt/ivle"
 
166
    public_host = "public.localhost"
 
167
    jail_base = "/home/informatics/jails"
 
168
    subjects_base = "/home/informatics/subjects"
 
169
# Always defaults
 
170
allowed_uids = "0"
387
171
 
388
172
# Try importing install_list, but don't fail if we can't, because listmake can
389
173
# function without it.
398
182
# as necessary, and include it in the distribution.
399
183
listmake_mimetypes = ['text/x-python', 'text/html',
400
184
    'application/x-javascript', 'application/javascript',
401
 
    'text/css', 'image/png', 'image/gif', 'application/xml']
 
185
    'text/css', 'image/png', 'application/xml']
402
186
 
403
187
# Main function skeleton from Guido van Rossum
404
188
# http://www.artima.com/weblogs/viewpost.jsp?thread=4829
489
273
to rebuild/install), just provide ivle_install_dir as the IVLE trunk
490
274
directory, and run build/install one time.
491
275
 
492
 
Creates lib/conf/conf.py and trampoline/conf.h.
 
276
Creates www/conf/conf.py and trampoline/conf.h.
493
277
 
494
 
Args are:"""
495
 
        for opt in config_options:
496
 
            print "    --" + opt.option_name
497
 
        print """As explained in the interactive prompt or conf.py.
 
278
Args are:
 
279
    --root_dir
 
280
    --ivle_install_dir
 
281
    --public_host
 
282
    --jail_base
 
283
    --subjects_base
 
284
    --allowed_uids
 
285
As explained in the interactive prompt or conf.py.
498
286
"""
499
287
    elif operation == 'build':
500
288
        print """python -O setup.py build [--dry|-n]
522
310
Copy subjects/ to subjects directory (unless --nosubjects specified).
523
311
 
524
312
--nojail        Do not copy the jail.
525
 
--nosubjects    Do not copy the subjects and exercises directories.
 
313
--nosubjects    Do not copy the subjects.
526
314
--dry | -n  Print out the actions but don't do anything."""
527
315
    elif operation == 'updatejails':
528
316
        print """sudo python setup.py updatejails [--dry|-n]
539
327
def listmake(args):
540
328
    # We build two separate lists, by walking www and console
541
329
    list_www = build_list_py_files('www')
542
 
    list_lib = build_list_py_files('lib')
 
330
    list_console = build_list_py_files('console')
543
331
    list_subjects = build_list_py_files('subjects', no_top_level=True)
544
 
    list_exercises = build_list_py_files('exercises', no_top_level=True)
545
 
    list_scripts = [
546
 
        "scripts/python-console",
547
 
        "scripts/fileservice",
548
 
        "scripts/serveservice",
549
 
        "scripts/usrmgt-server",
550
 
        "scripts/diffservice",
551
 
    ]
552
332
    # Make sure that the files generated by conf are in the list
553
333
    # (since listmake is typically run before conf)
554
 
    if "lib/conf/conf.py" not in list_lib:
555
 
        list_lib.append("lib/conf/conf.py")
 
334
    if "www/conf/conf.py" not in list_www:
 
335
        list_www.append("www/conf/conf.py")
 
336
    # Make sure that console/python-console is in the list
 
337
    if "console/python-console" not in list_console:
 
338
        list_console.append("console/python-console")
556
339
    # Write these out to a file
557
340
    cwd = os.getcwd()
558
341
    # the files that will be created/overwritten
572
355
list_www = """)
573
356
        writelist_pretty(file, list_www)
574
357
        file.write("""
575
 
# List of all installable files in lib directory.
576
 
list_lib = """)
577
 
        writelist_pretty(file, list_lib)
578
 
        file.write("""
579
 
# List of all installable files in scripts directory.
580
 
list_scripts = """)
581
 
        writelist_pretty(file, list_scripts)
 
358
# List of all installable files in console directory.
 
359
list_console = """)
 
360
        writelist_pretty(file, list_console)
582
361
        file.write("""
583
362
# List of all installable files in subjects directory.
584
363
# This is to install sample subjects and material.
585
364
list_subjects = """)
586
365
        writelist_pretty(file, list_subjects)
587
 
        file.write("""
588
 
# List of all installable files in exercises directory.
589
 
# This is to install sample exercise material.
590
 
list_exercises = """)
591
 
        writelist_pretty(file, list_exercises)
592
366
 
593
367
        file.close()
594
368
    except IOError, (errno, strerror):
634
408
        file.write(']\n')
635
409
 
636
410
def conf(args):
637
 
    global db_port, usrmgt_port
 
411
    global root_dir, ivle_install_dir, jail_base, subjects_base
 
412
    global public_host, allowed_uids
638
413
    # Set up some variables
639
414
 
640
415
    cwd = os.getcwd()
641
416
    # the files that will be created/overwritten
642
 
    conffile = os.path.join(cwd, "lib/conf/conf.py")
643
 
    jailconffile = os.path.join(cwd, "lib/conf/jailconf.py")
 
417
    conffile = os.path.join(cwd, "www/conf/conf.py")
644
418
    conf_hfile = os.path.join(cwd, "trampoline/conf.h")
645
 
    phpBBconffile = os.path.join(cwd, "www/php/phpBB3/config.php")
646
 
    usrmgtserver_initdfile = os.path.join(cwd, "doc/setup/usrmgt-server.init")
647
419
 
648
420
    # Get command-line arguments to avoid asking questions.
649
421
 
650
 
    optnames = []
651
 
    for opt in config_options:
652
 
        optnames.append(opt.option_name + "=")
653
 
    (opts, args) = getopt.gnu_getopt(args, "", optnames)
 
422
    (opts, args) = getopt.gnu_getopt(args, "", ['root_dir=',
 
423
                    'ivle_install_dir=', 'jail_base=', 'allowed_uids='])
654
424
 
655
425
    if args != []:
656
426
        print >>sys.stderr, "Invalid arguments:", string.join(args, ' ')
662
432
        print """This tool will create the following files:
663
433
    %s
664
434
    %s
665
 
    %s
666
 
    %s
667
 
    %s
668
435
prompting you for details about your configuration. The file will be
669
436
overwritten if it already exists. It will *not* install or deploy IVLE.
670
437
 
671
438
Please hit Ctrl+C now if you do not wish to do this.
672
 
""" % (conffile, jailconffile, conf_hfile, phpBBconffile, usrmgtserver_initdfile)
 
439
""" % (conffile, conf_hfile)
673
440
 
674
441
        # Get information from the administrator
675
442
        # If EOF is encountered at any time during the questioning, just exit
676
443
        # silently
677
444
 
678
 
        for opt in config_options:
679
 
            globals()[opt.option_name] = \
680
 
                query_user(globals()[opt.option_name], opt.prompt)
 
445
        root_dir = query_user(root_dir,
 
446
        """Root directory where IVLE is located (in URL space):""")
 
447
        ivle_install_dir = query_user(ivle_install_dir,
 
448
        'Root directory where IVLE will be installed (on the local file '
 
449
        'system):')
 
450
        jail_base = query_user(jail_base,
 
451
        """Root directory where the jails (containing user files) are stored
 
452
(on the local file system):""")
 
453
        subjects_base = query_user(subjects_base,
 
454
        """Root directory where the subject directories (containing worksheets
 
455
and other per-subject files) are stored (on the local file system):""")
 
456
        public_host = query_user(public_host,
 
457
        """Hostname which will cause the server to go into "public mode",
 
458
providing login-free access to student's published work:""")
 
459
        allowed_uids = query_user(allowed_uids,
 
460
        """UID of the web server process which will run IVLE.
 
461
Only this user may execute the trampoline. May specify multiple users as
 
462
a comma-separated list.
 
463
    (eg. "1002,78")""")
 
464
 
681
465
    else:
682
466
        opts = dict(opts)
683
467
        # Non-interactive mode. Parse the options.
684
 
        for opt in config_options:
685
 
            if '--' + opt.option_name in opts:
686
 
                globals()[opt.option_name] = opts['--' + opt.option_name]
 
468
        if '--root_dir' in opts:
 
469
            root_dir = opts['--root_dir']
 
470
        if '--ivle_install_dir' in opts:
 
471
            ivle_install_dir = opts['--ivle_install_dir']
 
472
        if '--jail_base' in opts:
 
473
            jail_base = opts['--jail_base']
 
474
        if '--subjects_base' in opts:
 
475
            jail_base = opts['--subjects_base']
 
476
        if '--public_host' in opts:
 
477
            public_host = opts['--public_host']
 
478
        if '--allowed_uids' in opts:
 
479
            allowed_uids = opts['--allowed_uids']
687
480
 
688
481
    # Error handling on input values
689
482
    try:
690
 
        allowed_uids_list = map(int, allowed_uids.split(','))
 
483
        allowed_uids = map(int, allowed_uids.split(','))
691
484
    except ValueError:
692
485
        print >>sys.stderr, (
693
486
        "Invalid UID list (%s).\n"
694
487
        "Must be a comma-separated list of integers." % allowed_uids)
695
488
        return 1
696
 
    try:
697
 
        db_port = int(db_port)
698
 
        if db_port < 0 or db_port >= 65536: raise ValueError()
699
 
    except ValueError:
700
 
        print >>sys.stderr, (
701
 
        "Invalid DB port (%s).\n"
702
 
        "Must be an integer between 0 and 65535." % repr(db_port))
703
 
        return 1
704
 
    try:
705
 
        usrmgt_port = int(usrmgt_port)
706
 
        if usrmgt_port < 0 or usrmgt_port >= 65536: raise ValueError()
707
 
    except ValueError:
708
 
        print >>sys.stderr, (
709
 
        "Invalid user management port (%s).\n"
710
 
        "Must be an integer between 0 and 65535." % repr(usrmgt_port))
711
 
        return 1
712
 
 
713
 
    # Generate the forum secret
714
 
    forum_secret = hashlib.md5(uuid.uuid4().bytes).hexdigest()
715
 
 
716
 
    # Write lib/conf/conf.py
 
489
 
 
490
    # Write www/conf/conf.py
717
491
 
718
492
    try:
719
493
        conf = open(conffile, "w")
722
496
# conf.py
723
497
# Miscellaneous application settings
724
498
 
725
 
""")
726
 
        for opt in config_options:
727
 
            conf.write('%s\n%s = %s\n' % (opt.comment, opt.option_name,
728
 
                repr(globals()[opt.option_name])))
729
 
 
730
 
        # Add the forum secret to the config file (regenerated each config)
731
 
        conf.write('forum_secret = "%s"\n' % (forum_secret))
732
 
 
733
 
        conf.close()
734
 
    except IOError, (errno, strerror):
735
 
        print "IO error(%s): %s" % (errno, strerror)
736
 
        sys.exit(1)
737
 
 
738
 
    print "Successfully wrote lib/conf/conf.py"
739
 
 
740
 
    # Write conf/jailconf.py
741
 
 
742
 
    try:
743
 
        conf = open(jailconffile, "w")
744
 
 
745
 
        # In the "in-jail" version of conf, we don't need MOST of the details
746
 
        # (it would be a security risk to have them here).
747
 
        # So we just write root_dir, and jail_base is "/".
748
 
        # (jail_base being "/" means "jail-relative" paths are relative to "/"
749
 
        # when inside the jail.)
750
 
        conf.write("""# IVLE Configuration File
751
 
# conf.py
752
 
# Miscellaneous application settings
753
 
# (User jail version)
754
 
 
755
499
 
756
500
# In URL space, where in the site is IVLE located. (All URLs will be prefixed
757
501
# with this).
758
502
# eg. "/" or "/ivle".
759
 
root_dir = %s
 
503
root_dir = "%s"
 
504
 
 
505
# In the local file system, where IVLE is actually installed.
 
506
# This directory should contain the "www" and "bin" directories.
 
507
ivle_install_dir = "%s"
 
508
 
 
509
# The server goes into "public mode" if the browser sends a request with this
 
510
# host. This is for security reasons - we only serve public student files on a
 
511
# separate domain to the main IVLE site.
 
512
# Public mode does not use cookies, and serves only public content.
 
513
# Private mode (normal mode) requires login, and only serves files relevant to
 
514
# the logged-in user.
 
515
public_host = "%s"
760
516
 
761
517
# In the local file system, where are the student/user file spaces located.
762
518
# The user jails are expected to be located immediately in subdirectories of
763
519
# this location.
764
 
jail_base = '/'
 
520
jail_base = "%s"
765
521
 
766
 
# The hostname for serving publicly accessible pages
767
 
public_host = %s
768
 
""" % (repr(root_dir),repr(public_host)))
 
522
# In the local file system, where are the per-subject file spaces located.
 
523
# The individual subject directories are expected to be located immediately
 
524
# in subdirectories of this location.
 
525
subjects_base = "%s"
 
526
""" % (root_dir, ivle_install_dir, public_host, jail_base, subjects_base))
769
527
 
770
528
        conf.close()
771
529
    except IOError, (errno, strerror):
772
530
        print "IO error(%s): %s" % (errno, strerror)
773
531
        sys.exit(1)
774
532
 
775
 
    print "Successfully wrote lib/conf/jailconf.py"
 
533
    print "Successfully wrote www/conf/conf.py"
776
534
 
777
535
    # Write trampoline/conf.h
778
536
 
797
555
 * (Note that root is an implicit member of this list).
798
556
 */
799
557
static const int allowed_uids[] = { %s };
800
 
""" % (repr(jail_base)[1:-1], repr(allowed_uids_list)[1:-1]))
801
 
    # Note: The above uses PYTHON reprs, not C reprs
802
 
    # However they should be the same with the exception of the outer
803
 
    # characters, which are stripped off and replaced
 
558
""" % (jail_base, repr(allowed_uids)[1:-1]))
804
559
 
805
560
        conf.close()
806
561
    except IOError, (errno, strerror):
809
564
 
810
565
    print "Successfully wrote trampoline/conf.h"
811
566
 
812
 
    # Write www/php/phpBB3/config.php
813
 
 
814
 
    try:
815
 
        conf = open(phpBBconffile, "w")
816
 
        
817
 
        # php-pg work around
818
 
        if db_host == 'localhost':
819
 
            forumdb_host = '127.0.0.1'
820
 
        else:
821
 
            forumdb_host = db_host
822
 
 
823
 
        conf.write( """<?php
824
 
// phpBB 3.0.x auto-generated configuration file
825
 
// Do not change anything in this file!
826
 
$dbms = 'postgres';
827
 
$dbhost = '""" + forumdb_host + """';
828
 
$dbport = '""" + str(db_port) + """';
829
 
$dbname = '""" + db_forumdbname + """';
830
 
$dbuser = '""" + db_user + """';
831
 
$dbpasswd = '""" + db_password + """';
832
 
 
833
 
$table_prefix = 'phpbb_';
834
 
$acm_type = 'file';
835
 
$load_extensions = '';
836
 
@define('PHPBB_INSTALLED', true);
837
 
// @define('DEBUG', true);
838
 
//@define('DEBUG_EXTRA', true);
839
 
 
840
 
$forum_secret = '""" + forum_secret +"""';
841
 
?>"""   )
842
 
    
843
 
        conf.close()
844
 
    except IOError, (errno, strerror):
845
 
        print "IO error(%s): %s" % (errno, strerror)
846
 
        sys.exit(1)
847
 
 
848
 
    print "Successfully wrote www/php/phpBB3/config.php"
849
 
 
850
 
    # Write lib/conf/usrmgt-server.init
851
 
 
852
 
    try:
853
 
        conf = open(usrmgtserver_initdfile, "w")
854
 
 
855
 
        conf.write( '''#! /bin/sh
856
 
 
857
 
# Works for Ubuntu. Check before using on other distributions
858
 
 
859
 
### BEGIN INIT INFO
860
 
# Provides:          usrmgt-server
861
 
# Required-Start:    $syslog $networking $urandom
862
 
# Required-Stop:     $syslog
863
 
# Default-Start:     2 3 4 5
864
 
# Default-Stop:      1
865
 
# Short-Description: IVLE user management server
866
 
# Description:       Daemon connecting to the IVLE user management database.
867
 
### END INIT INFO
868
 
 
869
 
PATH=/sbin:/bin:/usr/sbin:/usr/bin
870
 
DESC="IVLE user management server"
871
 
NAME=usrmgt-server
872
 
DAEMON=/opt/ivle/scripts/$NAME
873
 
DAEMON_ARGS="''' + str(usrmgt_port) + ''' ''' + usrmgt_magic + '''"
874
 
PIDFILE=/var/run/$NAME.pid
875
 
SCRIPTNAME=/etc/init.d/usrmgt-server
876
 
 
877
 
# Exit if the daemon does not exist 
878
 
test -f $DAEMON || exit 0
879
 
 
880
 
# Load the VERBOSE setting and other rcS variables
881
 
[ -f /etc/default/rcS ] && . /etc/default/rcS
882
 
 
883
 
# Define LSB log_* functions.
884
 
# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
885
 
. /lib/lsb/init-functions
886
 
 
887
 
#
888
 
# Function that starts the daemon/service
889
 
#
890
 
do_start()
891
 
{
892
 
        # Return
893
 
        #   0 if daemon has been started
894
 
        #   1 if daemon was already running
895
 
        #   2 if daemon could not be started
896
 
        start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
897
 
                || return 1
898
 
        start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \
899
 
                $DAEMON_ARGS \
900
 
                || return 2
901
 
        # Add code here, if necessary, that waits for the process to be ready
902
 
        # to handle requests from services started subsequently which depend
903
 
        # on this one.  As a last resort, sleep for some time.
904
 
}
905
 
 
906
 
#
907
 
# Function that stops the daemon/service
908
 
#
909
 
do_stop()
910
 
{
911
 
        # Return
912
 
        #   0 if daemon has been stopped
913
 
        #   1 if daemon was already stopped
914
 
        #   2 if daemon could not be stopped
915
 
        #   other if a failure occurred
916
 
        start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME
917
 
        RETVAL="$?"
918
 
        [ "$RETVAL" = 2 ] && return 2
919
 
        # Wait for children to finish too if this is a daemon that forks
920
 
        # and if the daemon is only ever run from this initscript.
921
 
        # If the above conditions are not satisfied then add some other code
922
 
        # that waits for the process to drop all resources that could be
923
 
        # needed by services started subsequently.  A last resort is to
924
 
        # sleep for some time.
925
 
        start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
926
 
        [ "$?" = 2 ] && return 2
927
 
        # Many daemons don't delete their pidfiles when they exit.
928
 
        rm -f $PIDFILE
929
 
        return "$RETVAL"
930
 
}
931
 
 
932
 
#
933
 
# Function that sends a SIGHUP to the daemon/service
934
 
#
935
 
do_reload() {
936
 
        #
937
 
        # If the daemon can reload its configuration without
938
 
        # restarting (for example, when it is sent a SIGHUP),
939
 
        # then implement that here.
940
 
        #
941
 
        start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME
942
 
        return 0
943
 
}
944
 
 
945
 
case "$1" in
946
 
  start)
947
 
    [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
948
 
        do_start
949
 
        case "$?" in
950
 
                0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
951
 
                2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
952
 
        esac
953
 
        ;;
954
 
  stop)
955
 
        [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
956
 
        do_stop
957
 
        case "$?" in
958
 
                0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
959
 
                2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
960
 
        esac
961
 
        ;;
962
 
  #reload|force-reload)
963
 
        #
964
 
        # If do_reload() is not implemented then leave this commented out
965
 
        # and leave 'force-reload' as an alias for 'restart'.
966
 
        #
967
 
        #log_daemon_msg "Reloading $DESC" "$NAME"
968
 
        #do_reload
969
 
        #log_end_msg $?
970
 
        #;;
971
 
  restart|force-reload)
972
 
        #
973
 
        # If the "reload" option is implemented then remove the
974
 
        # 'force-reload' alias
975
 
        #
976
 
        log_daemon_msg "Restarting $DESC" "$NAME"
977
 
        do_stop
978
 
        case "$?" in
979
 
          0|1)
980
 
                do_start
981
 
                case "$?" in
982
 
                        0) log_end_msg 0 ;;
983
 
                        1) log_end_msg 1 ;; # Old process is still running
984
 
                        *) log_end_msg 1 ;; # Failed to start
985
 
                esac
986
 
                ;;
987
 
          *)
988
 
                # Failed to stop
989
 
                log_end_msg 1
990
 
                ;;
991
 
        esac
992
 
        ;;
993
 
  *)
994
 
        #echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
995
 
        echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2
996
 
        exit 3
997
 
        ;;
998
 
esac
999
 
 
1000
 
:
1001
 
''')
1002
 
        
1003
 
        conf.close()
1004
 
    except IOError, (errno, strerror):
1005
 
        print "IO error(%s): %s" % (errno, strerror)
1006
 
        sys.exit(1)
1007
 
 
1008
 
    # fix permissions as the file contains the database password
1009
 
    try:
1010
 
        os.chmod('doc/setup/usrmgt-server.init', 0600)
1011
 
    except OSError, (errno, strerror):
1012
 
        print "WARNING: Couldn't chmod doc/setup/usrmgt-server.init:"
1013
 
        print "OS error(%s): %s" % (errno, strerror)
1014
 
 
1015
 
    print "Successfully wrote lib/conf/usrmgt-server.init"
1016
 
 
1017
567
    print
1018
568
    print "You may modify the configuration at any time by editing"
1019
569
    print conffile
1020
 
    print jailconffile
1021
570
    print conf_hfile
1022
 
    print phpBBconffile
1023
 
    print usrmgtserver_initdfile
1024
571
    print
1025
572
    return 0
1026
573
 
1045
592
    action_mkdir('jail/home', dry)
1046
593
    action_mkdir('jail/tmp', dry)
1047
594
 
1048
 
    # Chmod the tmp directory to world writable
1049
 
    action_chmod_w('jail/tmp', dry)
1050
 
 
1051
595
    # Copy all console and operating system files into the jail
1052
 
    action_copylist(install_list.list_scripts, 'jail/opt/ivle', dry)
 
596
    action_copylist(install_list.list_console, 'jail/opt/ivle', dry)
1053
597
    copy_os_files_jail(dry)
1054
598
    # Chmod the python console
1055
 
    action_chmod_x('jail/opt/ivle/scripts/python-console', dry)
1056
 
    action_chmod_x('jail/opt/ivle/scripts/fileservice', dry)
1057
 
    action_chmod_x('jail/opt/ivle/scripts/serveservice', dry)
 
599
    action_chmod_x('jail/opt/ivle/console/python-console', dry)
1058
600
    
1059
 
    # Also copy the IVLE lib directory into the jail
1060
 
    # This is necessary for running certain scripts
1061
 
    action_copylist(install_list.list_lib, 'jail/opt/ivle', dry)
1062
 
    # IMPORTANT: The file jail/opt/ivle/lib/conf/conf.py contains details
1063
 
    # which could compromise security if left in the jail (such as the DB
1064
 
    # password).
1065
 
    # The "safe" version is in jailconf.py. Delete conf.py and replace it with
1066
 
    # jailconf.py.
1067
 
    action_copyfile('lib/conf/jailconf.py',
1068
 
        'jail/opt/ivle/lib/conf/conf.py', dry)
1069
601
 
1070
602
    # Compile .py files into .pyc or .pyo files
1071
603
    compileall.compile_dir('www', quiet=True)
1072
 
    compileall.compile_dir('lib', quiet=True)
1073
 
    compileall.compile_dir('scripts', quiet=True)
1074
 
    compileall.compile_dir('jail/opt/ivle/lib', quiet=True)
1075
 
 
1076
 
    # Set up ivle.pth inside the jail
1077
 
    # Need to set /opt/ivle/lib to be on the import path
1078
 
    ivle_pth = \
1079
 
        "jail/usr/lib/python%s/site-packages/ivle.pth" % PYTHON_VERSION
1080
 
    f = open(ivle_pth, 'w')
1081
 
    f.write('/opt/ivle/lib\n')
1082
 
    f.close()
 
604
    compileall.compile_dir('console', quiet=True)
1083
605
 
1084
606
    return 0
1085
607
 
1127
649
    # chown trampoline to root and set setuid bit
1128
650
    action_chown_setuid(tramppath, dry)
1129
651
 
1130
 
    # Create a scripts directory to put the usrmgt-server in.
1131
 
    action_mkdir(os.path.join(ivle_install_dir, 'scripts'), dry)
1132
 
    usrmgtpath = os.path.join(ivle_install_dir, 'scripts/usrmgt-server')
1133
 
    action_copyfile('scripts/usrmgt-server', usrmgtpath, dry)
1134
 
    action_chmod_x(usrmgtpath, dry)
1135
 
 
1136
 
    # Copy the www and lib directories using the list
 
652
    # Copy the www directory using the list
1137
653
    action_copylist(install_list.list_www, ivle_install_dir, dry)
1138
 
    action_copylist(install_list.list_lib, ivle_install_dir, dry)
1139
 
    
1140
 
    # Copy the php directory
1141
 
    forum_dir = "www/php/phpBB3"
1142
 
    forum_path = os.path.join(ivle_install_dir, forum_dir)
1143
 
    action_copytree(forum_dir, forum_path, dry)
1144
 
    print "chown -R www-data:www-data %s" % forum_path
1145
 
    if not dry:
1146
 
        os.system("chown -R www-data:www-data %s" % forum_path)
1147
654
 
1148
655
    if not nojail:
1149
656
        # Copy the local jail directory built by the build action
1151
658
        # for all the students' jails).
1152
659
        action_copytree('jail', os.path.join(jail_base, 'template'), dry)
1153
660
    if not nosubjects:
1154
 
        # Copy the subjects and exercises directories across
 
661
        # Copy the subjects directory across
1155
662
        action_copylist(install_list.list_subjects, subjects_base, dry,
1156
663
            srcdir="./subjects")
1157
 
        action_copylist(install_list.list_exercises, exercises_base, dry,
1158
 
            srcdir="./exercises")
1159
664
 
1160
665
    # Append IVLE path to ivle.pth in python site packages
1161
666
    # (Unless it's already there)
1162
667
    ivle_pth = os.path.join(sys.prefix,
1163
668
        "lib/python%s/site-packages/ivle.pth" % PYTHON_VERSION)
1164
669
    ivle_www = os.path.join(ivle_install_dir, "www")
1165
 
    ivle_lib = os.path.join(ivle_install_dir, "lib")
1166
670
    write_ivle_pth = True
1167
 
    write_ivle_lib_pth = True
1168
671
    try:
1169
672
        file = open(ivle_pth, 'r')
1170
673
        for line in file:
1171
674
            if line.strip() == ivle_www:
1172
675
                write_ivle_pth = False
1173
 
            elif line.strip() == ivle_lib:
1174
 
                write_ivle_lib_pth = False
1175
 
        file.close()
 
676
                break
1176
677
    except (IOError, OSError):
1177
678
        pass
1178
679
    if write_ivle_pth:
1179
680
        action_append(ivle_pth, ivle_www)
1180
 
    if write_ivle_lib_pth:
1181
 
        action_append(ivle_pth, ivle_lib)
1182
681
 
1183
682
    return 0
1184
683
 
1246
745
    if ret != 0:
1247
746
        raise RunError(prog, ret)
1248
747
 
1249
 
def action_remove(path, dry):
1250
 
    """Calls rmtree, deleting the target file if it exists."""
1251
 
    try:
1252
 
        print "rm -r", path
1253
 
        if not dry:
1254
 
            shutil.rmtree(path, True)
1255
 
    except OSError, (err, msg):
1256
 
        if err != errno.EEXIST:
1257
 
            raise
1258
 
        # Otherwise, didn't exist, so we don't care
1259
 
 
1260
748
def action_rename(src, dst, dry):
1261
749
    """Calls rename. Deletes the target if it already exists."""
1262
 
    action_remove(dst, dry)
 
750
    if os.access(dst, os.F_OK):
 
751
        print "rm -r", dst
 
752
        if not dry:
 
753
            shutil.rmtree(dst, True)
1263
754
    print "mv ", src, dst
1264
755
    if dry: return
1265
756
    try:
1285
776
    directories as necessary.
1286
777
 
1287
778
    See shutil.copytree."""
1288
 
    # Allow copying over itself
1289
 
    if (os.path.normpath(os.path.join(os.getcwd(),src)) ==
1290
 
        os.path.normpath(os.path.join(os.getcwd(),dst))):
1291
 
        return
1292
 
    action_remove(dst, dry)
 
779
    if os.access(dst, os.F_OK):
 
780
        print "rm -r", dst
 
781
        if not dry:
 
782
            shutil.rmtree(dst, True)
1293
783
    print "cp -r", src, dst
1294
784
    if dry: return
1295
785
    shutil.copytree(src, dst, True)
1298
788
    """Hard-links an entire directory tree. Same as copytree but the created
1299
789
    files are hard-links not actual copies. Removes the existing destination.
1300
790
    """
1301
 
    action_remove(dst, dry)
 
791
    if os.access(dst, os.F_OK):
 
792
        print "rm -r", dst
 
793
        if not dry:
 
794
            shutil.rmtree(dst, True)
1302
795
    print "<cp with hardlinks> -r", src, dst
1303
796
    if dry: return
1304
797
    common.makeuser.linktree(src, dst)
1373
866
            | stat.S_ISUID | stat.S_IRUSR | stat.S_IWUSR)
1374
867
 
1375
868
def action_chmod_x(file, dry):
1376
 
    """Chmod 755 a file (sets permissions to rwxr-xr-x)."""
1377
 
    print "chmod 755", file
1378
 
    if not dry:
1379
 
        os.chmod(file, stat.S_IXUSR | stat.S_IRUSR | stat.S_IWUSR
1380
 
            | stat.S_IXGRP | stat.S_IRGRP | stat.S_IXOTH | stat.S_IROTH)
1381
 
 
1382
 
 
1383
 
def action_chmod_w(file, dry):
1384
 
    """Chmod 777 a file (sets permissions to rwxrwxrwx)."""
1385
 
    print "chmod 777", file
1386
 
    if not dry:
1387
 
        os.chmod(file, stat.S_IXUSR | stat.S_IRUSR | stat.S_IWUSR
1388
 
            | stat.S_IXGRP | stat.S_IWGRP | stat.S_IRGRP | stat.S_IXOTH
1389
 
            | stat.S_IWOTH | stat.S_IROTH)
 
869
    """Chmod +xs a file (sets execute permission)."""
 
870
    print "chmod u+rwx", file
 
871
    if not dry:
 
872
        os.chmod(file, stat.S_IXUSR | stat.S_IRUSR | stat.S_IWUSR)
1390
873
 
1391
874
def query_user(default, prompt):
1392
875
    """Prompts the user for a string, which is read from a line of stdin.