1
1
# IVLE - Informatics Virtual Learning Environment
2
# Copyright (C) 2007-2008 The University of Melbourne
2
# Copyright (C) 2007-2009 The University of Melbourne
4
4
# This program is free software; you can redistribute it and/or modify
5
5
# it under the terms of the GNU General Public License as published by
15
15
# along with this program; if not, write to the Free Software
16
16
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22
# Allows creation of users. This sets up the following:
23
# * User's jail and home directory within the jail.
24
# * Subversion repository (TODO)
25
# * Check out Subversion workspace into jail (TODO)
26
# * Database details for user
29
# TODO: Sanitize login name and other fields.
30
# Users must not be called "temp" or "template".
32
# TODO: When creating a new home directory, chown it to its owner
34
# TODO: In chown_to_webserver:
35
# Do not call os.system("chown www-data") - use Python lib
36
# and use the web server uid given in conf. (Several places).
18
"""User and group filesystem management helpers."""
101
82
def rebuild_svn_group_config(store, config):
102
83
"""Build the complete SVN configuration file for groups
103
85
@param config: An ivle.config.Config object.
105
87
conf_name = config['paths']['svn']['group_conf']
123
105
chown_to_webserver(conf_name)
125
107
def make_svn_auth(store, login, config, throw_on_error=True):
126
"""Setup svn authentication for the given user.
127
Uses the given DB store object. Does not commit to the db.
108
"""Create a Subversion password for a user.
110
Generates a new random Subversion password, and assigns it to the user.
111
The password is added to Apache's Subversion authentication file.
129
113
# filename is, eg, /var/lib/ivle/svn/ivle.auth
130
114
filename = config['paths']['svn']['auth_ivle']
137
121
user = ivle.database.User.get_by_login(store, login)
138
122
user.svn_pass = unicode(passwd)
140
res = os.system("htpasswd -%smb %s %s %s" % (create, filename,
124
res = subprocess.call(['htpasswd', '-%smb' % create,
125
filename, login, passwd])
142
126
if res != 0 and throw_on_error:
143
127
raise Exception("Unable to create ivle-auth for %s" % login)
151
def generate_manifest(basedir, targetdir, parent=''):
152
""" From a basedir and a targetdir work out which files are missing or out
153
of date and need to be added/updated and which files are redundant and need
156
parent: This is used for the recursive call to track the relative paths
157
that we have decended.
160
cmp = filecmp.dircmp(basedir, targetdir)
162
# Add all new files and files that have changed
163
to_add = [os.path.join(parent,x) for x in (cmp.left_only + cmp.diff_files)]
165
# Remove files that are redundant
166
to_remove = [os.path.join(parent,x) for x in cmp.right_only]
169
for d in cmp.common_dirs:
170
newbasedir = os.path.join(basedir, d)
171
newtargetdir = os.path.join(targetdir, d)
172
newparent = os.path.join(parent, d)
173
(sadd,sremove) = generate_manifest(newbasedir, newtargetdir, newparent)
177
return (to_add, to_remove)
180
135
def make_jail(user, config, force=True):
181
"""Creates a new user's jail space, in the jail directory as configured in
136
"""Create or update a user's jail.
184
This only creates things within /home - everything else is expected to be
185
part of another UnionFS branch.
138
Only the user-specific parts of the jail are created here - everything
139
else is expected to be part of another aufs branch.
187
141
Returns the path to the user's home directory.
189
143
Chowns the user's directory within the jail to the given UID.
191
force: If false, exception if jail already exists for this user.
192
If true (default), overwrites it, but preserves home directory.
145
@param force: If False, raise an exception if the user already has a jail.
146
If True (default), rebuild the jail preserving /home.
194
148
# MUST run as root or some of this may fail
195
149
if os.getuid() != 0:
247
201
return userhomedir
249
203
def make_ivle_conf(username, user_jail_dir, svn_pass, sys_config):
204
"""Generate an ivle.conf for a user's jail.
251
206
Creates (overwriting any existing file, and creating directories) a
252
207
file /etc/ivle/ivle.conf in a given user's jail.
253
209
@param username: Username.
254
210
@param user_jail_dir: User's jail dir, ie. ['jails']['src'] + username
255
211
@param svn_pass: User's SVN password.
278
234
def make_etc_passwd(username, user_jail_dir, template_dir, unixid):
235
"""Create a passwd file for a user's jail.
280
237
Creates /etc/passwd in the given user's jail. This will be identical to
281
238
that in the template jail, except for the added entry for this user.
290
247
passwd_file.write('%s:x:%d:%d::/home/%s:/bin/bash'
291
248
% (username, unixid, unixid, username))
292
249
passwd_file.close()
294
def mount_jail(login, config):
295
# This is where we'll mount to...
296
destdir = os.path.join(config['paths']['jails']['mounts'], login)
297
# ... and this is where we'll get the user bits.
298
srcdir = os.path.join(config['paths']['jails']['src'], login)
300
if not os.path.exists(destdir):
302
if os.system('/bin/mount -t aufs -o dirs=%s:%s=ro none %s'
303
% (srcdir, config['paths']['jails']['template'],
305
logging.info("mounted user %s's jail." % login)
307
logging.error("failed to mount user %s's jail!" % login)
308
except Exception, message:
309
logging.warning(str(message))