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.
74
133
# Also this allows you to hit Return to accept the existing value.
76
135
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
137
root_dir = confmodule.root_dir
141
ivle_install_dir = confmodule.ivle_install_dir
143
ivle_install_dir = "/opt/ivle"
145
public_host = confmodule.public_host
147
public_host = "public.localhost"
149
jail_base = confmodule.jail_base
151
jail_base = "/home/informatics/jails"
153
subjects_base = confmodule.subjects_base
155
subjects_base = "/home/informatics/subjects"
80
156
except ImportError:
81
157
# Just set reasonable defaults
82
158
root_dir = "/ivle"
83
159
ivle_install_dir = "/opt/ivle"
160
public_host = "public.localhost"
84
161
jail_base = "/home/informatics/jails"
162
subjects_base = "/home/informatics/subjects"
86
164
allowed_uids = "0"
344
430
jail_base = query_user(jail_base,
345
431
"""Root directory where the jails (containing user files) are stored
346
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:""")
347
439
allowed_uids = query_user(allowed_uids,
348
440
"""UID of the web server process which will run IVLE.
349
441
Only this user may execute the trampoline. May specify multiple users as
390
486
# This directory should contain the "www" and "bin" directories.
391
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.
393
497
# In the local file system, where are the student/user file spaces located.
394
498
# 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))
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):
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
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