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

« back to all changes in this revision

Viewing changes to scripts/usrmgt-server

  • Committer: William Grant
  • Date: 2009-05-27 06:49:25 UTC
  • Revision ID: grantw@unimelb.edu.au-20090527064925-avjig8opo22t1lur
Drop ivle.conf usage from ivle.pulldown_subj.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#!/usr/bin/python
2
 
 
3
 
import os
4
 
import pysvn
5
 
import subprocess
6
 
import sys
7
 
import urllib
8
 
from functools import partial
9
 
import traceback
10
 
 
11
 
import conf
12
 
import common.db
13
 
import common.chat
14
 
import common.makeuser
15
 
import common.studpath
16
 
 
17
 
# usage:
18
 
#   usrmgt-server <port> <magic>
19
 
 
20
 
# User management operations:
21
 
#   - Create local user
22
 
#   - [Re]Create jail for a user
23
 
#       - Create a svn repository for a user
24
 
#           - create repository
25
 
#           - svn config
26
 
#           - svn auth
27
 
#       - Checkout repository as home directory
28
 
#       - /etc/passwd entry
29
 
#   - Disable a user's account
30
 
#   - Enable a user's account
31
 
#   - Remove a user
32
 
#   - Rebuild svn config
33
 
#   - Rebuild svn auth file
34
 
#   - Rebuild passwd + push to nodes.
35
 
 
36
 
DEBUG_PRINT = True
37
 
 
38
 
def create_user(props):
39
 
    """Create the database record for the given user.
40
 
       Expected properties:
41
 
        login       - used as a unix login name and svn repository name.
42
 
                      STRING REQUIRED 
43
 
        unixid      - the unix uid under which execution will take place
44
 
                      on the behalf of the user. Don't use 0! If not specified
45
 
                      or None, one will be allocated from the configured
46
 
                      numeric range.
47
 
                      INT OPTIONAL
48
 
        password    - the clear-text password for the user. If this property is
49
 
                      absent or None, this is an indication that external
50
 
                      authentication should be used (i.e. LDAP).
51
 
                      STRING OPTIONAL
52
 
        email       - the user's email address.
53
 
                      STRING OPTIONAL
54
 
        nick        - the display name to use.
55
 
                      STRING REQUIRED
56
 
        fullname    - The name of the user for results and/or other official
57
 
                      purposes.
58
 
                      STRING REQUIRED
59
 
        rolenm      - The user's role. Must be one of "anyone", "student",
60
 
                      "tutor", "lecturer", "admin".
61
 
                      STRING/ENUM REQUIRED
62
 
        studentid   - If supplied and not None, the student id of the user for
63
 
                      results and/or other official purposes.
64
 
                      STRING OPTIONAL
65
 
       Return Value: the uid associated with the user. INT
66
 
    """
67
 
 
68
 
    if 'unixid' not in props or props['unixid'] is None:
69
 
        # For the time being, just choose a random unixid.
70
 
        # This may result in duplicates, but the unixid is essentially
71
 
        # a monitoring/logging convenience only. Oh, and dups could kill
72
 
        # each other. <sigh>
73
 
        props['unixid'] = random.randrange(5000,10000)
74
 
        # raise NotImplementedError, "No algorithm for creating uids yet!"
75
 
        # unixid = invent-uid
76
 
        # props['unixid'] = unixid
77
 
 
78
 
    common.makeuser.make_user_db(**props)
79
 
 
80
 
    return int(props['unixid'])
81
 
 
82
 
def update_user(props):
83
 
    """Create the database record for the given user.
84
 
       Expected properties:
85
 
        login       - user who is making the change (not necessarily the one
86
 
                      being updated).
87
 
        update      - dict of fields to be updated. The fields are all those
88
 
                      in the login table of the db.
89
 
                      'login' required.
90
 
                      Omitted fields will not be set.
91
 
    """
92
 
    update = props['update']
93
 
    # Note: "login" is special - it is not part of the kwargs to
94
 
    # db.update_user, but the first arg - used to find the user to update.
95
 
    # However it doesn't need any special treatment here.
96
 
 
97
 
    db = common.db.DB()
98
 
    db.update_user(**update)
99
 
    db.close()
100
 
 
101
 
def get_login(login, passwd, _realm, _login, _may_save):
102
 
    """Callback function used by pysvn for authentication.
103
 
    """
104
 
    log("Getting password for %s (realm %s)" % (login, _realm))
105
 
    return (True, login, passwd, False)
106
 
 
107
 
def activate_user(props):
108
 
    """Create the on-disk stuff for the given user.
109
 
       Sets the state of the user in the db from pending to enabled.
110
 
       Expected properties:
111
 
        login       - the user name for the jail
112
 
                      STRING REQUIRED
113
 
       Return Value: None
114
 
    """
115
 
 
116
 
    login = props['login']
117
 
 
118
 
    db = common.db.DB()
119
 
 
120
 
    try:
121
 
 
122
 
        # FIXME: check we're pending
123
 
 
124
 
        details = db.get_user(login)
125
 
 
126
 
        # make svn config/auth
127
 
 
128
 
        log("Creating repo")
129
 
        common.makeuser.make_svn_repo(login, throw_on_error=False)
130
 
        log("Creating svn config")
131
 
        common.makeuser.make_svn_config(login, throw_on_error=False)
132
 
        log("Creating svn auth")
133
 
        passwd = common.makeuser.make_svn_auth(login, throw_on_error=False)
134
 
        log("passwd: %s" % passwd)
135
 
 
136
 
        svn = pysvn.Client()
137
 
        svn.callback_get_login = partial(get_login, login, passwd)
138
 
 
139
 
        if conf.svn_addr[-1] != '/':
140
 
            conf.svn_addr = conf.svn_addr + "/"
141
 
    
142
 
        # FIXME: This should be a loop over enrolements.
143
 
        #        We're not going to fix this now because it requires
144
 
        #        a large amount of admin console work to manage subject
145
 
        #        offerings.
146
 
        #        Instead, we're just going to use a single offering with
147
 
        #        a "short" name of "info1".
148
 
        log("Creating /info1")
149
 
        try:
150
 
            svn.mkdir(conf.svn_addr + login + "/info1",
151
 
                      "Initial creation of work directory for Informatics 1")
152
 
        except Exception, exc:
153
 
            log("While mkdiring info1: %s" % str(exc))
154
 
            pass
155
 
        log("Creating /submissions")
156
 
        try:
157
 
            svn.mkdir(conf.svn_addr + login + "/submissions",
158
 
                      "Initial creation of submissions directory")
159
 
        except Exception, exc:
160
 
            log("While mkdiring submissions: %s" % str(exc))
161
 
            pass
162
 
        log("Creating /stuff")
163
 
        try:
164
 
            svn.mkdir(conf.svn_addr + login + "/stuff",
165
 
                      "Initial creation of directory for miscellania")
166
 
        except Exception, exc:
167
 
            log("While mkdiring stuff: %s" % str(exc))
168
 
            pass
169
 
 
170
 
        log("Creating jail")
171
 
        common.makeuser.make_jail(login, details.unixid)
172
 
 
173
 
        # FIXME: <hack>
174
 
 
175
 
        tcf_path = os.path.join(conf.jail_base, 'template/opt/ivle/lib/conf/conf.py')
176
 
        cf_path = os.path.join(conf.jail_base, login, 'opt/ivle/lib/conf/conf.py')
177
 
 
178
 
        os.remove(cf_path)
179
 
        cf = open(cf_path, "w")
180
 
        cf.write(open(tcf_path, "r").read())
181
 
        cf.write("# The login name for the owner of the jail\n")
182
 
        cf.write("login = %s\n" % repr(login))
183
 
        cf.write("\n")
184
 
        cf.write("# The subversion-only password for the owner of the jail\n")
185
 
        cf.write("svn_pass = %s\n" % repr(passwd))
186
 
        cf.close()
187
 
 
188
 
        # FIXME: </hack>
189
 
 
190
 
        log("Checking out directories in the jail")
191
 
        try:
192
 
            svn.checkout(conf.svn_addr + login + "/stuff",
193
 
                         common.studpath.url_to_local(login + "/stuff")[1])
194
 
        except Exception, exc:
195
 
            log("While mkdiring stuff: %s" % str(exc))
196
 
            pass
197
 
        try:
198
 
            svn.checkout(conf.svn_addr + login + "/submissions",
199
 
                         common.studpath.url_to_local(login + "/submissions")[1])
200
 
        except Exception, exc:
201
 
            log("While mkdiring submissions: %s" % str(exc))
202
 
            pass
203
 
        try:
204
 
            svn.checkout(conf.svn_addr + login + "/info1",
205
 
                         common.studpath.url_to_local(login + "/info1")[1])
206
 
        except Exception, exc:
207
 
            log("While mkdiring info1: %s" % str(exc))
208
 
            pass
209
 
 
210
 
        # FIXME: should this be nicer?
211
 
        os.system("chown -R %d:%d %s" \
212
 
                % (details.unixid, details.unixid,
213
 
                   common.studpath.url_to_local(login)[1]))
214
 
 
215
 
 
216
 
        log("Enabling user")
217
 
        db.update_user(login, state='enabled')
218
 
 
219
 
        return {"response": "okay"}
220
 
 
221
 
    finally:
222
 
        db.close()
223
 
 
224
 
actions = {
225
 
        'create_user':create_user,
226
 
        'update_user':update_user,
227
 
        'activate_user':activate_user,
228
 
    }
229
 
 
230
 
def log(msg):
231
 
    """Writes a message to stderr, but only if DEBUG_PRINT is True.
232
 
    """
233
 
    global DEBUG_PRINT
234
 
    if DEBUG_PRINT:
235
 
        print >>sys.stderr, msg
236
 
 
237
 
def dispatch(props):
238
 
    log(repr(props))
239
 
    action = props.keys()[0]
240
 
    return actions[action](props[action])
241
 
 
242
 
if __name__ == "__main__":
243
 
    port = int(sys.argv[1])
244
 
    magic = sys.argv[2]
245
 
 
246
 
    common.chat.start_server(port, magic, False, dispatch)