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

« back to all changes in this revision

Viewing changes to scripts/usrmgt-server

ivle.webapp.admin, ivle.webapp.groups, ivle.webapp.tutorial: Remove broken
    'py:strip's from <html> elements.

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