74
# Import modules from the website is tricky since they're in the www
76
sys.path.append(os.path.join(os.getcwd(), 'lib'))
78
import common.makeuser
80
# Determine which Python version (2.4 or 2.5, for example) we are running,
81
# and use that as the filename to the Python directory.
82
# Just get the first 3 characters of sys.version.
83
PYTHON_VERSION = sys.version[0:3]
86
"""A configuration option; one of the things written to conf.py."""
87
def __init__(self, option_name, default, prompt, comment):
88
"""Creates a configuration option.
89
option_name: Name of the variable in conf.py. Also name of the
90
command-line argument to setup.py conf.
91
default: Default value for this variable.
92
prompt: (Short) string presented during the interactive prompt in
94
comment: (Long) comment string stored in conf.py. Each line of this
95
string should begin with a '#'.
97
self.option_name = option_name
98
self.default = default
100
self.comment = comment
102
# Configuration options, defaults and descriptions
104
config_options.append(ConfigOption("root_dir", "/",
105
"""Root directory where IVLE is located (in URL space):""",
107
# In URL space, where in the site is IVLE located. (All URLs will be prefixed
109
# eg. "/" or "/ivle"."""))
110
config_options.append(ConfigOption("ivle_install_dir", "/opt/ivle",
111
'Root directory where IVLE will be installed (on the local file '
114
# In the local file system, where IVLE is actually installed.
115
# This directory should contain the "www" and "bin" directories."""))
116
config_options.append(ConfigOption("jail_base", "/home/informatics/jails",
117
"""Location of Directories
118
=======================
119
Root directory where the jails (containing user files) are stored
120
(on the local file system):""",
122
# In the local file system, where are the student/user file spaces located.
123
# The user jails are expected to be located immediately in subdirectories of
124
# this location."""))
125
config_options.append(ConfigOption("subjects_base",
126
"/home/informatics/subjects",
127
"""Root directory where the subject directories (containing worksheets
128
and other per-subject files) are stored (on the local file system):""",
130
# In the local file system, where are the per-subject file spaces located.
131
# The individual subject directories are expected to be located immediately
132
# in subdirectories of this location."""))
133
config_options.append(ConfigOption("exercises_base",
134
"/home/informatics/exercises",
135
"""Root directory where the exercise directories (containing
136
subject-independent exercise sheets) are stored (on the local file
139
# In the local file system, where are the subject-independent exercise sheet
140
# file spaces located."""))
141
config_options.append(ConfigOption("tos_path",
142
"/home/informatics/tos.html",
143
"""Location where the Terms of Service document is stored (on the local
146
# In the local file system, where is the Terms of Service document located."""))
147
config_options.append(ConfigOption("motd_path",
148
"/home/informatics/motd.html",
149
"""Location where the Message of the Day document is stored (on the local
152
# In the local file system, where is the Message of the Day document
153
# located. This is an HTML file (just the body fragment), which will
154
# be displayed on the login page. It is optional."""))
155
config_options.append(ConfigOption("public_host", "public.localhost",
156
"""Hostname which will cause the server to go into "public mode",
157
providing login-free access to student's published work:""",
159
# The server goes into "public mode" if the browser sends a request with this
160
# host. This is for security reasons - we only serve public student files on a
161
# separate domain to the main IVLE site.
162
# Public mode does not use cookies, and serves only public content.
163
# Private mode (normal mode) requires login, and only serves files relevant to
164
# the logged-in user."""))
165
config_options.append(ConfigOption("allowed_uids", "33",
166
"""UID of the web server process which will run IVLE.
167
Only this user may execute the trampoline. May specify multiple users as
168
a comma-separated list.
171
# The User-ID of the web server process which will run IVLE, and any other
172
# users who are allowed to run the trampoline. This is stores as a string of
173
# comma-separated integers, simply because it is not used within Python, only
174
# used by the setup program to write to conf.h (see setup.py config)."""))
175
config_options.append(ConfigOption("db_host", "localhost",
176
"""PostgreSQL Database config
177
==========================
178
Hostname of the DB server:""",
180
### PostgreSQL Database config ###
181
# Database server hostname"""))
182
config_options.append(ConfigOption("db_port", "5432",
183
"""Port of the DB server:""",
185
# Database server port"""))
186
config_options.append(ConfigOption("db_dbname", "ivle",
187
"""Database name:""",
190
config_options.append(ConfigOption("db_forumdbname", "ivle_forum",
191
"""Forum Database name:""",
193
# Forum Database name"""))
194
config_options.append(ConfigOption("db_user", "postgres",
195
"""Username for DB server login:""",
197
# Database username"""))
198
config_options.append(ConfigOption("db_password", "",
199
"""Password for DB server login:
200
(Caution: This password is stored in plaintext in lib/conf/conf.py)""",
202
# Database password"""))
203
config_options.append(ConfigOption("auth_modules", "ldap_auth",
204
"""Authentication config
205
=====================
206
Comma-separated list of authentication modules. Only "ldap" is available
209
# Comma-separated list of authentication modules.
210
# These refer to importable Python modules in the www/auth directory.
211
# Modules "ldap" and "guest" are available in the source tree, but
212
# other modules may be plugged in to auth against organisation-specific
213
# auth backends."""))
214
config_options.append(ConfigOption("ldap_url", "ldaps://www.example.com",
215
"""(LDAP options are only relevant if "ldap" is included in the list of
217
URL for LDAP authentication server:""",
219
# URL for LDAP authentication server"""))
220
config_options.append(ConfigOption("ldap_format_string",
221
"uid=%s,ou=users,o=example",
222
"""Format string for LDAP auth request:
223
(Must contain a single "%s" for the user's login name)""",
225
# Format string for LDAP auth request
226
# (Must contain a single "%s" for the user's login name)"""))
227
config_options.append(ConfigOption("svn_addr", "http://svn.localhost/",
230
The base url for accessing subversion repositories:""",
232
# The base url for accessing subversion repositories."""))
233
config_options.append(ConfigOption("svn_conf", "/opt/ivle/svn/svn.conf",
234
"""The location of the subversion configuration file used by apache
235
to host the user repositories:""",
237
# The location of the subversion configuration file used by
238
# apache to host the user repositories."""))
239
config_options.append(ConfigOption("svn_repo_path", "/home/informatics/repositories",
240
"""The root directory for the subversion repositories:""",
242
# The root directory for the subversion repositories."""))
243
config_options.append(ConfigOption("svn_auth_ivle", "/opt/ivle/svn/ivle.auth",
244
"""The location of the password file used to authenticate users
245
of the subversion repository from the ivle server:""",
247
# The location of the password file used to authenticate users
248
# of the subversion repository from the ivle server."""))
249
config_options.append(ConfigOption("svn_auth_local", "/opt/ivle/svn/local.auth",
250
"""The location of the password file used to authenticate local users
251
of the subversion repository:""",
253
# The location of the password file used to authenticate local users
254
# of the subversion repository."""))
255
config_options.append(ConfigOption("usrmgt_host", "localhost",
256
"""User Management Server config
257
============================
258
The hostname where the usrmgt-server runs:""",
260
# The hostname where the usrmgt-server runs."""))
261
config_options.append(ConfigOption("usrmgt_port", "2178",
262
"""The port where the usrmgt-server runs:""",
264
# The port where the usrmgt-server runs."""))
265
config_options.append(ConfigOption("usrmgt_magic", "",
266
"""The password for the usrmgt-server:""",
268
# The password for the usrmgt-server."""))
71
270
# Try importing existing conf, but if we can't just set up defaults
72
271
# The reason for this is that these settings are used by other phases
73
272
# of setup besides conf, so we need to know them.
74
273
# Also this allows you to hit Return to accept the existing value.
76
confmodule = __import__("www/conf/conf")
77
root_dir = confmodule.root_dir
78
ivle_install_dir = confmodule.ivle_install_dir
79
jail_base = confmodule.jail_base
275
confmodule = __import__("lib/conf/conf")
276
for opt in config_options:
278
globals()[opt.option_name] = confmodule.__dict__[opt.option_name]
280
globals()[opt.option_name] = opt.default
80
281
except ImportError:
81
282
# Just set reasonable defaults
83
ivle_install_dir = "/opt/ivle"
84
jail_base = "/home/informatics/jails"
283
for opt in config_options:
284
globals()[opt.option_name] = opt.default
88
286
# Try importing install_list, but don't fail if we can't, because listmake can
89
287
# function without it.
326
561
print """This tool will create the following files:
329
567
prompting you for details about your configuration. The file will be
330
568
overwritten if it already exists. It will *not* install or deploy IVLE.
332
570
Please hit Ctrl+C now if you do not wish to do this.
333
""" % (conffile, conf_hfile)
571
""" % (conffile, jailconffile, conf_hfile, phpBBconffile, usrmgtserver_initdfile)
335
573
# Get information from the administrator
336
574
# If EOF is encountered at any time during the questioning, just exit
339
root_dir = query_user(root_dir,
340
"""Root directory where IVLE is located (in URL space):""")
341
ivle_install_dir = query_user(ivle_install_dir,
342
'Root directory where IVLE will be installed (on the local file '
344
jail_base = query_user(jail_base,
345
"""Root directory where the jails (containing user files) are stored
346
(on the local file system):""")
347
allowed_uids = query_user(allowed_uids,
348
"""UID of the web server process which will run IVLE.
349
Only this user may execute the trampoline. May specify multiple users as
350
a comma-separated list.
577
for opt in config_options:
578
globals()[opt.option_name] = \
579
query_user(globals()[opt.option_name], opt.prompt)
354
581
opts = dict(opts)
355
582
# Non-interactive mode. Parse the options.
356
if '--root_dir' in opts:
357
root_dir = opts['--root_dir']
358
if '--ivle_install_dir' in opts:
359
ivle_install_dir = opts['--ivle_install_dir']
360
if '--jail_base' in opts:
361
jail_base = opts['--jail_base']
362
if '--allowed_uids' in opts:
363
allowed_uids = opts['--allowed_uids']
583
for opt in config_options:
584
if '--' + opt.option_name in opts:
585
globals()[opt.option_name] = opts['--' + opt.option_name]
365
587
# Error handling on input values
367
allowed_uids = map(int, allowed_uids.split(','))
589
allowed_uids_list = map(int, allowed_uids.split(','))
368
590
except ValueError:
369
591
print >>sys.stderr, (
370
592
"Invalid UID list (%s).\n"
371
593
"Must be a comma-separated list of integers." % allowed_uids)
374
# Write www/conf/conf.py
596
db_port = int(db_port)
597
if db_port < 0 or db_port >= 65536: raise ValueError()
599
print >>sys.stderr, (
600
"Invalid DB port (%s).\n"
601
"Must be an integer between 0 and 65535." % repr(db_port))
604
usrmgt_port = int(usrmgt_port)
605
if usrmgt_port < 0 or usrmgt_port >= 65536: raise ValueError()
607
print >>sys.stderr, (
608
"Invalid user management port (%s).\n"
609
"Must be an integer between 0 and 65535." % repr(usrmgt_port))
612
# Generate the forum secret
613
forum_secret = hashlib.md5(uuid.uuid4().bytes).hexdigest()
615
# Write lib/conf/conf.py
377
618
conf = open(conffile, "w")
381
622
# Miscellaneous application settings
625
for opt in config_options:
626
conf.write('%s\n%s = %s\n' % (opt.comment, opt.option_name,
627
repr(globals()[opt.option_name])))
629
# Add the forum secret to the config file (regenerated each config)
630
conf.write('forum_secret = "%s"\n' % (forum_secret))
633
except IOError, (errno, strerror):
634
print "IO error(%s): %s" % (errno, strerror)
637
print "Successfully wrote lib/conf/conf.py"
639
# Write conf/jailconf.py
642
conf = open(jailconffile, "w")
644
# In the "in-jail" version of conf, we don't need MOST of the details
645
# (it would be a security risk to have them here).
646
# So we just write root_dir, and jail_base is "/".
647
# (jail_base being "/" means "jail-relative" paths are relative to "/"
648
# when inside the jail.)
649
conf.write("""# IVLE Configuration File
651
# Miscellaneous application settings
652
# (User jail version)
384
655
# In URL space, where in the site is IVLE located. (All URLs will be prefixed
386
657
# eg. "/" or "/ivle".
389
# In the local file system, where IVLE is actually installed.
390
# This directory should contain the "www" and "bin" directories.
391
ivle_install_dir = "%s"
393
660
# In the local file system, where are the student/user file spaces located.
394
661
# The user jails are expected to be located immediately in subdirectories of
398
# Which application to load by default (if the user navigates to the top level
399
# of the site). This is the app's URL name.
400
# Note that if this app requires authentication, the user will first be
401
# presented with the login screen.
403
""" % (root_dir, ivle_install_dir, jail_base, default_app))
665
# The hostname for serving publicly accessible pages
667
""" % (repr(root_dir),repr(public_host)))
406
670
except IOError, (errno, strerror):
407
671
print "IO error(%s): %s" % (errno, strerror)
410
print "Successfully wrote www/conf/conf.py"
674
print "Successfully wrote lib/conf/jailconf.py"
412
676
# Write trampoline/conf.h
442
709
print "Successfully wrote trampoline/conf.h"
711
# Write www/php/phpBB3/config.php
714
conf = open(phpBBconffile, "w")
717
if db_host == 'localhost':
718
forumdb_host = '127.0.0.1'
720
forumdb_host = db_host
723
// phpBB 3.0.x auto-generated configuration file
724
// Do not change anything in this file!
726
$dbhost = '""" + forumdb_host + """';
727
$dbport = '""" + str(db_port) + """';
728
$dbname = '""" + db_forumdbname + """';
729
$dbuser = '""" + db_user + """';
730
$dbpasswd = '""" + db_password + """';
732
$table_prefix = 'phpbb_';
734
$load_extensions = '';
735
@define('PHPBB_INSTALLED', true);
736
// @define('DEBUG', true);
737
//@define('DEBUG_EXTRA', true);
739
$forum_secret = '""" + forum_secret +"""';
743
except IOError, (errno, strerror):
744
print "IO error(%s): %s" % (errno, strerror)
747
print "Successfully wrote www/php/phpBB3/config.php"
749
# Write lib/conf/usrmgt-server.init
752
conf = open(usrmgtserver_initdfile, "w")
754
conf.write( '''#! /bin/sh
756
# Works for Ubuntu. Check before using on other distributions
759
# Provides: usrmgt-server
760
# Required-Start: $syslog $networking $urandom
761
# Required-Stop: $syslog
762
# Default-Start: 2 3 4 5
764
# Short-Description: IVLE user management server
765
# Description: Daemon connecting to the IVLE user management database.
768
PATH=/sbin:/bin:/usr/sbin:/usr/bin
769
DESC="IVLE user management server"
771
DAEMON=/opt/ivle/scripts/$NAME
772
DAEMON_ARGS="''' + str(usrmgt_port) + ''' ''' + usrmgt_magic + '''"
773
PIDFILE=/var/run/$NAME.pid
774
SCRIPTNAME=/etc/init.d/usrmgt-server
776
# Exit if the daemon does not exist
777
test -f $DAEMON || exit 0
779
# Load the VERBOSE setting and other rcS variables
780
[ -f /etc/default/rcS ] && . /etc/default/rcS
782
# Define LSB log_* functions.
783
# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
784
. /lib/lsb/init-functions
787
# Function that starts the daemon/service
792
# 0 if daemon has been started
793
# 1 if daemon was already running
794
# 2 if daemon could not be started
795
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
797
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \
800
# Add code here, if necessary, that waits for the process to be ready
801
# to handle requests from services started subsequently which depend
802
# on this one. As a last resort, sleep for some time.
806
# Function that stops the daemon/service
811
# 0 if daemon has been stopped
812
# 1 if daemon was already stopped
813
# 2 if daemon could not be stopped
814
# other if a failure occurred
815
start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME
817
[ "$RETVAL" = 2 ] && return 2
818
# Wait for children to finish too if this is a daemon that forks
819
# and if the daemon is only ever run from this initscript.
820
# If the above conditions are not satisfied then add some other code
821
# that waits for the process to drop all resources that could be
822
# needed by services started subsequently. A last resort is to
823
# sleep for some time.
824
start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
825
[ "$?" = 2 ] && return 2
826
# Many daemons don't delete their pidfiles when they exit.
832
# Function that sends a SIGHUP to the daemon/service
836
# If the daemon can reload its configuration without
837
# restarting (for example, when it is sent a SIGHUP),
838
# then implement that here.
840
start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME
846
[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
849
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
850
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
854
[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
857
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
858
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
861
#reload|force-reload)
863
# If do_reload() is not implemented then leave this commented out
864
# and leave 'force-reload' as an alias for 'restart'.
866
#log_daemon_msg "Reloading $DESC" "$NAME"
870
restart|force-reload)
872
# If the "reload" option is implemented then remove the
873
# 'force-reload' alias
875
log_daemon_msg "Restarting $DESC" "$NAME"
882
1) log_end_msg 1 ;; # Old process is still running
883
*) log_end_msg 1 ;; # Failed to start
893
#echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
894
echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2
903
except IOError, (errno, strerror):
904
print "IO error(%s): %s" % (errno, strerror)
907
# fix permissions as the file contains the database password
909
os.chmod('doc/setup/usrmgt-server.init', 0600)
910
except OSError, (errno, strerror):
911
print "WARNING: Couldn't chmod doc/setup/usrmgt-server.init:"
912
print "OS error(%s): %s" % (errno, strerror)
914
print "Successfully wrote lib/conf/usrmgt-server.init"
445
917
print "You may modify the configuration at any time by editing"
922
print usrmgtserver_initdfile
458
933
print "Dry run (no actions will be executed\n"
935
if not dry and os.geteuid() != 0:
936
print >>sys.stderr, "Must be root to run build"
937
print >>sys.stderr, "(I need to chroot)."
940
# Find out the revison number
941
revnum = get_svn_revision()
942
print "Building Revision %s"%str(revnum)
944
vfile = open('BUILD-VERSION','w')
945
vfile.write(str(revnum) + '\n')
460
948
# Compile the trampoline
461
action_runprog('gcc', ['-Wall', '-o', 'trampoline/trampoline',
462
'trampoline/trampoline.c'], dry)
950
os.chdir('trampoline')
951
action_runprog('make', [], dry)
464
954
# Create the jail and its subdirectories
465
955
# Note: Other subdirs will be made by copying files
466
action_mkdir('jail', dry)
467
action_mkdir('jail/home', dry)
468
action_mkdir('jail/tmp', dry)
956
action_runprog('./buildjail.sh', [], dry)
470
958
# Copy all console and operating system files into the jail
471
action_copylist(install_list.list_console, 'jail/opt/ivle', dry)
472
copy_os_files_jail(dry)
959
action_copylist(install_list.list_scripts, 'jail/opt/ivle', dry)
960
# Chmod the python console
961
action_chmod_x('jail/opt/ivle/scripts/python-console', dry)
962
action_chmod_x('jail/opt/ivle/scripts/fileservice', dry)
963
action_chmod_x('jail/opt/ivle/scripts/serveservice', dry)
965
# Also copy the IVLE lib directory into the jail
966
# This is necessary for running certain scripts
967
action_copylist(install_list.list_lib, 'jail/opt/ivle', dry)
968
# IMPORTANT: The file jail/opt/ivle/lib/conf/conf.py contains details
969
# which could compromise security if left in the jail (such as the DB
971
# The "safe" version is in jailconf.py. Delete conf.py and replace it with
973
action_copyfile('lib/conf/jailconf.py',
974
'jail/opt/ivle/lib/conf/conf.py', dry)
474
976
# Compile .py files into .pyc or .pyo files
475
977
compileall.compile_dir('www', quiet=True)
476
compileall.compile_dir('console', quiet=True)
978
compileall.compile_dir('lib', quiet=True)
979
compileall.compile_dir('scripts', quiet=True)
980
compileall.compile_dir('jail/opt/ivle/lib', quiet=True)
982
# Set up ivle.pth inside the jail
983
# Need to set /opt/ivle/lib to be on the import path
985
"jail/usr/lib/python%s/site-packages/ivle.pth" % PYTHON_VERSION
986
f = open(ivle_pth, 'w')
987
f.write('/opt/ivle/lib\n')
480
def copy_os_files_jail(dry):
481
"""Copies necessary Operating System files from their usual locations
482
into the jail/ directory of the cwd."""
483
# Currently source paths are configured for Ubuntu.
484
copy_file_to_jail('/lib/ld-linux.so.2', dry)
485
copy_file_to_jail('/lib/tls/i686/cmov/libc.so.6', dry)
486
copy_file_to_jail('/lib/tls/i686/cmov/libdl.so.2', dry)
487
copy_file_to_jail('/lib/tls/i686/cmov/libm.so.6', dry)
488
copy_file_to_jail('/lib/tls/i686/cmov/libpthread.so.0', dry)
489
copy_file_to_jail('/lib/tls/i686/cmov/libutil.so.1', dry)
490
copy_file_to_jail('/usr/bin/python2.5', dry)
491
action_symlink('python2.5', 'jail/usr/bin/python', dry)
492
action_copytree('/usr/lib/python2.5', 'jail/usr/lib/python2.5', dry)
494
992
def copy_file_to_jail(src, dry):
495
993
"""Copies a single file from an absolute location into the same location
496
994
within the jail. src must begin with a '/'. The jail will be located
522
1022
# chown trampoline to root and set setuid bit
523
1023
action_chown_setuid(tramppath, dry)
525
# Copy the www directory using the list
1025
# Create a scripts directory to put the usrmgt-server in.
1026
action_mkdir(os.path.join(ivle_install_dir, 'scripts'), dry)
1027
usrmgtpath = os.path.join(ivle_install_dir, 'scripts/usrmgt-server')
1028
action_copyfile('scripts/usrmgt-server', usrmgtpath, dry)
1029
action_chmod_x(usrmgtpath, dry)
1031
# Copy the www and lib directories using the list
526
1032
action_copylist(install_list.list_www, ivle_install_dir, dry)
1033
action_copylist(install_list.list_lib, ivle_install_dir, dry)
1035
# Copy the php directory
1036
forum_dir = "www/php/phpBB3"
1037
forum_path = os.path.join(ivle_install_dir, forum_dir)
1038
action_copytree(forum_dir, forum_path, dry)
1039
print "chown -R www-data:www-data %s" % forum_path
1041
os.system("chown -R www-data:www-data %s" % forum_path)
529
1044
# Copy the local jail directory built by the build action
530
# to the jails template directory (it will be used as a template
531
# for all the students' jails).
532
action_copytree('jail', os.path.join(jail_base, 'template'), dry)
1045
# to the jails __staging__ directory (it will be used to help build
1046
# all the students' jails).
1047
action_copytree('jail', os.path.join(jail_base, '__staging__'), dry)
1049
# Copy the subjects and exercises directories across
1050
action_copylist(install_list.list_subjects, subjects_base, dry,
1051
srcdir="./subjects")
1052
action_copylist(install_list.list_exercises, exercises_base, dry,
1053
srcdir="./exercises")
1055
# Append IVLE path to ivle.pth in python site packages
1056
# (Unless it's already there)
1057
ivle_pth = os.path.join(sys.prefix,
1058
"lib/python%s/site-packages/ivle.pth" % PYTHON_VERSION)
1059
ivle_www = os.path.join(ivle_install_dir, "www")
1060
ivle_lib = os.path.join(ivle_install_dir, "lib")
1061
write_ivle_pth = True
1062
write_ivle_lib_pth = True
1064
file = open(ivle_pth, 'r')
1066
if line.strip() == ivle_www:
1067
write_ivle_pth = False
1068
elif line.strip() == ivle_lib:
1069
write_ivle_lib_pth = False
1071
except (IOError, OSError):
1074
action_append(ivle_pth, ivle_www)
1075
if write_ivle_lib_pth:
1076
action_append(ivle_pth, ivle_lib)
1079
# Create the ivle working revision record file
1080
action_mkdir(os.path.join(ivle_install_dir, 'version'), dry)
1081
ivle_revision_record_file = os.path.join(ivle_install_dir, 'version/ivle-revision.txt')
1084
conf = open(ivle_revision_record_file, "w")
1086
conf.write( "# IVLE code revision listing generated by running 'svn status -v ..' from " + os.getcwd() + "\n#\n\n")
1089
except IOError, (errno, strerror):
1090
print "IO error(%s): %s" % (errno, strerror)
1093
os.system("svn status -v .. >> %s" % ivle_revision_record_file)
1095
print "Wrote IVLE code revision status to %s" % ivle_revision_record_file
1099
def updatejails(args):
1100
# Get "dry" variable from command line
1101
(opts, args) = getopt.gnu_getopt(args, "n", ['dry'])
1103
dry = '-n' in opts or '--dry' in opts
1106
print "Dry run (no actions will be executed\n"
1108
if not dry and os.geteuid() != 0:
1109
print >>sys.stderr, "Must be root to run install"
1110
print >>sys.stderr, "(I need to chown some files)."
1113
# Update the staging jail directory in case it hasn't been installed
1115
action_copytree('jail', os.path.join(jail_base, '__staging__'), dry)
1117
# Re-link all the files in all students jails.
1118
for dir in os.listdir(jail_base):
1119
if dir == '__staging__': continue
1120
# First back up the student's home directory
1121
temp_home = os.tmpnam()
1122
action_rename(os.path.join(jail_base, dir, 'home'), temp_home, dry)
1123
# Delete the student's jail and relink the jail files
1124
action_linktree(os.path.join(jail_base, '__staging__'),
1125
os.path.join(jail_base, dir), dry)
1126
# Restore the student's home directory
1127
action_rename(temp_home, os.path.join(jail_base, dir, 'home'), dry)
1128
# Set up the user's home directory just in case they don't have a
1129
# directory for this yet
1130
action_mkdir(os.path.join(jail_base, dir, 'home', dir), dry)