71
# Import modules from the website is tricky since they're in the www
73
sys.path.append(os.path.join(os.getcwd(), 'www'))
75
import common.makeuser
77
# Operating system files to copy over into the jail.
78
# These will be copied from the given place on the OS file system into the
79
# same place within the jail.
82
'/lib/tls/i686/cmov/libc.so.6',
83
'/lib/tls/i686/cmov/libdl.so.2',
84
'/lib/tls/i686/cmov/libm.so.6',
85
'/lib/tls/i686/cmov/libpthread.so.0',
86
'/lib/tls/i686/cmov/libutil.so.1',
89
# These 2 files do not exist in Ubuntu
90
#'/etc/ld.so.preload',
91
#'/etc/ld.so.nohwcap',
98
# Needed by matplotlib
99
'/usr/lib/i686/cmov/libssl.so.0.9.8',
100
'/usr/lib/i686/cmov/libcrypto.so.0.9.8',
101
'/lib/tls/i686/cmov/libnsl.so.1',
102
'/usr/lib/libz.so.1',
103
'/usr/lib/atlas/liblapack.so.3',
104
'/usr/lib/atlas/libblas.so.3',
105
'/usr/lib/libg2c.so.0',
106
'/usr/lib/libstdc++.so.6',
107
'/usr/lib/libfreetype.so.6',
108
'/usr/lib/libpng12.so.0',
109
'/usr/lib/libBLT.2.4.so.8.4',
110
'/usr/lib/libtk8.4.so.0',
111
'/usr/lib/libtcl8.4.so.0',
112
'/usr/lib/tcl8.4/init.tcl',
113
'/usr/lib/libX11.so.6',
114
'/usr/lib/libXau.so.6',
115
'/usr/lib/libXdmcp.so.6',
116
'/lib/libgcc_s.so.1',
119
# Symlinks to make within the jail. Src mapped to dst.
121
'python2.5': 'jail/usr/bin/python',
123
# Trees to copy. Src mapped to dst (these will be passed to action_copytree).
125
'/usr/lib/python2.5': 'jail/usr/lib/python2.5',
126
'/usr/share/matplotlib': 'jail/usr/share/matplotlib',
127
'/etc/ld.so.conf.d': 'jail/etc/ld.so.conf.d',
71
130
# Try importing existing conf, but if we can't just set up defaults
72
131
# The reason for this is that these settings are used by other phases
73
132
# of setup besides conf, so we need to know them.
84
143
ivle_install_dir = "/opt/ivle"
145
public_host = confmodule.public_host
147
public_host = "public.localhost"
86
149
jail_base = confmodule.jail_base
88
151
jail_base = "/home/informatics/jails"
153
subjects_base = confmodule.subjects_base
155
subjects_base = "/home/informatics/subjects"
89
156
except ImportError:
90
157
# Just set reasonable defaults
91
158
root_dir = "/ivle"
92
159
ivle_install_dir = "/opt/ivle"
160
public_host = "public.localhost"
93
161
jail_base = "/home/informatics/jails"
162
subjects_base = "/home/informatics/subjects"
95
164
allowed_uids = "0"
232
305
--nojail Do not copy the jail.
233
306
--dry | -n Print out the actions but don't do anything."""
307
elif operation == 'updatejails':
308
print """sudo python setup.py updatejails [--dry|-n]
310
Copy jail/ to each subdirectory in jails directory.
312
--dry | -n Print out the actions but don't do anything."""
235
314
print >>sys.stderr, (
236
315
"""Invalid operation '%s'. Try python setup.py help."""
350
430
jail_base = query_user(jail_base,
351
431
"""Root directory where the jails (containing user files) are stored
352
432
(on the local file system):""")
433
subjects_base = query_user(subjects_base,
434
"""Root directory where the subject directories (containing worksheets
435
and other per-subject files) are stored (on the local file system):""")
436
public_host = query_user(public_host,
437
"""Hostname which will cause the server to go into "public mode",
438
providing login-free access to student's published work:""")
353
439
allowed_uids = query_user(allowed_uids,
354
440
"""UID of the web server process which will run IVLE.
355
441
Only this user may execute the trampoline. May specify multiple users as
365
451
ivle_install_dir = opts['--ivle_install_dir']
366
452
if '--jail_base' in opts:
367
453
jail_base = opts['--jail_base']
454
if '--subjects_base' in opts:
455
jail_base = opts['--subjects_base']
456
if '--public_host' in opts:
457
public_host = opts['--public_host']
368
458
if '--allowed_uids' in opts:
369
459
allowed_uids = opts['--allowed_uids']
396
486
# This directory should contain the "www" and "bin" directories.
397
487
ivle_install_dir = "%s"
489
# The server goes into "public mode" if the browser sends a request with this
490
# host. This is for security reasons - we only serve public student files on a
491
# separate domain to the main IVLE site.
492
# Public mode does not use cookies, and serves only public content.
493
# Private mode (normal mode) requires login, and only serves files relevant to
494
# the logged-in user.
399
497
# In the local file system, where are the student/user file spaces located.
400
498
# The user jails are expected to be located immediately in subdirectories of
403
""" % (root_dir, ivle_install_dir, jail_base))
502
# In the local file system, where are the per-subject file spaces located.
503
# The individual subject directories are expected to be located immediately
504
# in subdirectories of this location.
506
""" % (root_dir, ivle_install_dir, public_host, jail_base, subjects_base))
406
509
except IOError, (errno, strerror):
470
573
# Copy all console and operating system files into the jail
471
574
action_copylist(install_list.list_console, 'jail/opt/ivle', dry)
472
575
copy_os_files_jail(dry)
576
# Chmod the python console
577
action_chmod_x('jail/opt/ivle/console/python-console', dry)
474
580
# Compile .py files into .pyc or .pyo files
475
581
compileall.compile_dir('www', quiet=True)
481
587
"""Copies necessary Operating System files from their usual locations
482
588
into the jail/ directory of the cwd."""
483
589
# 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)
590
for filename in JAIL_FILES:
591
copy_file_to_jail(filename, dry)
592
for src, dst in JAIL_LINKS.items():
593
action_symlink(src, dst, dry)
594
for src, dst in JAIL_COPYTREES.items():
595
action_copytree(src, dst, dry)
494
597
def copy_file_to_jail(src, dry):
495
598
"""Copies a single file from an absolute location into the same location
531
634
# for all the students' jails).
532
635
action_copytree('jail', os.path.join(jail_base, 'template'), dry)
637
# Append IVLE path to ivle.pth in python site packages
638
# (Unless it's already there)
639
ivle_pth = os.path.join(sys.prefix,
640
"lib/python2.5/site-packages/ivle.pth")
641
ivle_www = os.path.join(ivle_install_dir, "www")
642
write_ivle_pth = True
644
file = open(ivle_pth, 'r')
646
if line.strip() == ivle_www:
647
write_ivle_pth = False
649
except (IOError, OSError):
652
action_append(ivle_pth, ivle_www)
656
def updatejails(args):
657
# Get "dry" variable from command line
658
(opts, args) = getopt.gnu_getopt(args, "n", ['dry'])
660
dry = '-n' in opts or '--dry' in opts
663
print "Dry run (no actions will be executed\n"
665
if not dry and os.geteuid() != 0:
666
print >>sys.stderr, "Must be root to run install"
667
print >>sys.stderr, "(I need to chown some files)."
670
# Update the template jail directory in case it hasn't been installed
672
action_copytree('jail', os.path.join(jail_base, 'template'), dry)
674
# Re-link all the files in all students jails.
675
for dir in os.listdir(jail_base):
676
if dir == 'template': continue
677
# First back up the student's home directory
678
temp_home = os.tmpnam()
679
action_rename(os.path.join(jail_base, dir, 'home'), temp_home, dry)
680
# Delete the student's jail and relink the jail files
681
action_linktree(os.path.join(jail_base, 'template'),
682
os.path.join(jail_base, dir), dry)
683
# Restore the student's home directory
684
action_rename(temp_home, os.path.join(jail_base, dir, 'home'), dry)
685
# Set up the user's home directory just in case they don't have a
686
# directory for this yet
687
action_mkdir(os.path.join(jail_base, dir, 'home', dir), dry)
536
691
# The actions call Python os functions but print actions and handle dryness.
563
718
raise RunError(prog, ret)
720
def action_rename(src, dst, dry):
721
"""Calls rename. Deletes the target if it already exists."""
722
if os.access(dst, os.F_OK):
725
shutil.rmtree(dst, True)
726
print "mv ", src, dst
730
except OSError, (err, msg):
731
if err != errno.EEXIST:
565
734
def action_mkdir(path, dry):
566
735
"""Calls mkdir. Silently ignored if the directory already exists.
567
736
Creates all parent directories as necessary."""
588
757
shutil.copytree(src, dst, True)
759
def action_linktree(src, dst, dry):
760
"""Hard-links an entire directory tree. Same as copytree but the created
761
files are hard-links not actual copies. Removes the existing destination.
763
if os.access(dst, os.F_OK):
766
shutil.rmtree(dst, True)
767
print "<cp with hardlinks> -r", src, dst
769
common.makeuser.linktree(src, dst)
590
771
def action_copylist(srclist, dst, dry):
591
772
"""Copies all files in a list to a new location. The files in the list
592
773
are read relative to the current directory, and their destinations are the
635
816
os.symlink(src, dst)
818
def action_append(ivle_pth, ivle_www):
819
file = open(ivle_pth, 'a+')
820
file.write(ivle_www + '\n')
637
823
def action_chown_setuid(file, dry):
638
824
"""Chowns a file to root, and sets the setuid bit on the file.
639
825
Calling this function requires the euid to be root.
648
834
os.chmod(file, stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH
649
835
| stat.S_ISUID | stat.S_IRUSR | stat.S_IWUSR)
837
def action_chmod_x(file, dry):
838
"""Chmod +xs a file (sets execute permission)."""
839
print "chmod u+rwx", file
841
os.chmod(file, stat.S_IXUSR | stat.S_IRUSR | stat.S_IWUSR)
651
843
def query_user(default, prompt):
652
844
"""Prompts the user for a string, which is read from a line of stdin.
653
845
Exits silently if EOF is encountered. Returns the string, with spaces