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

440 by drtomc
usrmgt: move the usrmgt sever to a better place.
1
#!/usr/bin/python
2
522 by drtomc
Add quite a lot of stuff to get usrmgt happening.
3
import os
4
import pysvn
5
import subprocess
440 by drtomc
usrmgt: move the usrmgt sever to a better place.
6
import sys
522 by drtomc
Add quite a lot of stuff to get usrmgt happening.
7
import urllib
8
from functools import partial
548 by mattgiuca
www/apps/userservice: Allows unixid as an argument to create_user.
9
import traceback
567 by drtomc
usrmgt: use proper logging.
10
import logging
684 by apeel
Added an initialisor to usrmgt-server which creates a PID file in /var/run. Needed for the /etc/init.d/ script.
11
import errno
440 by drtomc
usrmgt: move the usrmgt sever to a better place.
12
522 by drtomc
Add quite a lot of stuff to get usrmgt happening.
13
import conf
473 by drtomc
usrmgt: progress the skeleton a bit further.
14
import common.db
440 by drtomc
usrmgt: move the usrmgt sever to a better place.
15
import common.chat
16
import common.makeuser
522 by drtomc
Add quite a lot of stuff to get usrmgt happening.
17
import common.studpath
440 by drtomc
usrmgt: move the usrmgt sever to a better place.
18
19
# usage:
20
#   usrmgt-server <port> <magic>
21
452 by drtomc
usrmgt: checkpoint work on the usrmgt server.
22
# User management operations:
23
#   - Create local user
24
#   - [Re]Create jail for a user
25
#       - Create a svn repository for a user
26
#           - create repository
27
#           - svn config
28
#           - svn auth
29
#       - Checkout repository as home directory
30
#       - /etc/passwd entry
31
#   - Disable a user's account
32
#   - Enable a user's account
33
#   - Remove a user
34
#   - Rebuild svn config
35
#   - Rebuild svn auth file
36
#   - Rebuild passwd + push to nodes.
37
440 by drtomc
usrmgt: move the usrmgt sever to a better place.
38
def create_user(props):
452 by drtomc
usrmgt: checkpoint work on the usrmgt server.
39
    """Create the database record for the given user.
40
       Expected properties:
548 by mattgiuca
www/apps/userservice: Allows unixid as an argument to create_user.
41
        login       - used as a unix login name and svn repository name.
452 by drtomc
usrmgt: checkpoint work on the usrmgt server.
42
                      STRING REQUIRED 
548 by mattgiuca
www/apps/userservice: Allows unixid as an argument to create_user.
43
        unixid      - the unix uid under which execution will take place
454 by drtomc
usrmgt-server: more work.
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).
452 by drtomc
usrmgt: checkpoint work on the usrmgt server.
51
                      STRING OPTIONAL
464 by mattgiuca
usermgt-server: Added email.
52
        email       - the user's email address.
53
                      STRING OPTIONAL
452 by drtomc
usrmgt: checkpoint work on the usrmgt server.
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
454 by drtomc
usrmgt-server: more work.
62
        studentid   - If supplied and not None, the student id of the user for
452 by drtomc
usrmgt: checkpoint work on the usrmgt server.
63
                      results and/or other official purposes.
64
                      STRING OPTIONAL
454 by drtomc
usrmgt-server: more work.
65
       Return Value: the uid associated with the user. INT
452 by drtomc
usrmgt: checkpoint work on the usrmgt server.
66
    """
440 by drtomc
usrmgt: move the usrmgt sever to a better place.
67
548 by mattgiuca
www/apps/userservice: Allows unixid as an argument to create_user.
68
    if 'unixid' not in props or props['unixid'] is None:
541 by drtomc
Implement a vege algorithm for allocating unix uids: rnd.
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>
548 by mattgiuca
www/apps/userservice: Allows unixid as an argument to create_user.
73
        props['unixid'] = random.randrange(5000,10000)
541 by drtomc
Implement a vege algorithm for allocating unix uids: rnd.
74
        # raise NotImplementedError, "No algorithm for creating uids yet!"
548 by mattgiuca
www/apps/userservice: Allows unixid as an argument to create_user.
75
        # unixid = invent-uid
76
        # props['unixid'] = unixid
77
78
    common.makeuser.make_user_db(**props)
79
80
    return int(props['unixid'])
454 by drtomc
usrmgt-server: more work.
81
551 by mattgiuca
userservice/usrmgt-server: Added update_user action to both.
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
522 by drtomc
Add quite a lot of stuff to get usrmgt happening.
101
def get_login(login, passwd, _realm, _login, _may_save):
102
    """Callback function used by pysvn for authentication.
103
    """
571 by drtomc
usrmgt: improve the logging. Amazing what happens when you actually read
104
    logging.debug("Getting password for %s (realm %s)" % (login, _realm))
522 by drtomc
Add quite a lot of stuff to get usrmgt happening.
105
    return (True, login, passwd, False)
106
473 by drtomc
usrmgt: progress the skeleton a bit further.
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.
454 by drtomc
usrmgt-server: more work.
110
       Expected properties:
473 by drtomc
usrmgt: progress the skeleton a bit further.
111
        login       - the user name for the jail
454 by drtomc
usrmgt-server: more work.
112
                      STRING REQUIRED
456 by drtomc
usrmgt-server: a bit more work.
113
       Return Value: None
454 by drtomc
usrmgt-server: more work.
114
    """
456 by drtomc
usrmgt-server: a bit more work.
115
473 by drtomc
usrmgt: progress the skeleton a bit further.
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
522 by drtomc
Add quite a lot of stuff to get usrmgt happening.
126
        # make svn config/auth
127
571 by drtomc
usrmgt: improve the logging. Amazing what happens when you actually read
128
        logging.debug("Creating repo")
522 by drtomc
Add quite a lot of stuff to get usrmgt happening.
129
        common.makeuser.make_svn_repo(login, throw_on_error=False)
571 by drtomc
usrmgt: improve the logging. Amazing what happens when you actually read
130
        logging.debug("Creating svn config")
522 by drtomc
Add quite a lot of stuff to get usrmgt happening.
131
        common.makeuser.make_svn_config(login, throw_on_error=False)
571 by drtomc
usrmgt: improve the logging. Amazing what happens when you actually read
132
        logging.debug("Creating svn auth")
522 by drtomc
Add quite a lot of stuff to get usrmgt happening.
133
        passwd = common.makeuser.make_svn_auth(login, throw_on_error=False)
571 by drtomc
usrmgt: improve the logging. Amazing what happens when you actually read
134
        logging.debug("passwd: %s" % passwd)
522 by drtomc
Add quite a lot of stuff to get usrmgt happening.
135
136
        svn = pysvn.Client()
137
        svn.callback_get_login = partial(get_login, login, passwd)
528 by drtomc
usrmgt-server: robustify svn url handling a bit.
138
139
        if conf.svn_addr[-1] != '/':
140
            conf.svn_addr = conf.svn_addr + "/"
522 by drtomc
Add quite a lot of stuff to get usrmgt happening.
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".
571 by drtomc
usrmgt: improve the logging. Amazing what happens when you actually read
148
        logging.debug("Creating /info1")
522 by drtomc
Add quite a lot of stuff to get usrmgt happening.
149
        try:
150
            svn.mkdir(conf.svn_addr + login + "/info1",
151
                      "Initial creation of work directory for Informatics 1")
152
        except Exception, exc:
571 by drtomc
usrmgt: improve the logging. Amazing what happens when you actually read
153
            logging.warning("While mkdiring info1: %s" % str(exc))
522 by drtomc
Add quite a lot of stuff to get usrmgt happening.
154
            pass
571 by drtomc
usrmgt: improve the logging. Amazing what happens when you actually read
155
        logging.debug("Creating /stuff")
522 by drtomc
Add quite a lot of stuff to get usrmgt happening.
156
        try:
157
            svn.mkdir(conf.svn_addr + login + "/stuff",
158
                      "Initial creation of directory for miscellania")
159
        except Exception, exc:
571 by drtomc
usrmgt: improve the logging. Amazing what happens when you actually read
160
            logging.warning("While mkdiring stuff: %s" % str(exc))
522 by drtomc
Add quite a lot of stuff to get usrmgt happening.
161
            pass
162
571 by drtomc
usrmgt: improve the logging. Amazing what happens when you actually read
163
        logging.debug("Creating jail")
522 by drtomc
Add quite a lot of stuff to get usrmgt happening.
164
        common.makeuser.make_jail(login, details.unixid)
165
166
        # FIXME: <hack>
167
168
        tcf_path = os.path.join(conf.jail_base, 'template/opt/ivle/lib/conf/conf.py')
169
        cf_path = os.path.join(conf.jail_base, login, 'opt/ivle/lib/conf/conf.py')
170
171
        os.remove(cf_path)
172
        cf = open(cf_path, "w")
173
        cf.write(open(tcf_path, "r").read())
174
        cf.write("# The login name for the owner of the jail\n")
175
        cf.write("login = %s\n" % repr(login))
176
        cf.write("\n")
177
        cf.write("# The subversion-only password for the owner of the jail\n")
178
        cf.write("svn_pass = %s\n" % repr(passwd))
179
        cf.close()
180
676 by mattgiuca
usrmgt-server: Moved SVN checkout code from activate_me into a separate
181
        # Check out the repositories into the student's home dir
680 by mattgiuca
usrmgt-server: Desperate hack to make activate_me work again - do_checkout is
182
        # FIXME: Call do_checkout instead of replicating this code.
183
        # (do_checkout currently doesn't work)
184
        #do_checkout(props)
185
186
        # FIXME: </hack>
187
188
        logging.debug("Checking out directories in the jail")
189
        try:
190
            svn.checkout(conf.svn_addr + login + "/stuff",
191
                         common.studpath.url_to_local(login + "/stuff")[1])
192
            os.system("chown -R %d:%d %s" \
193
                    % (details.unixid, details.unixid,
194
                       common.studpath.url_to_local(login + "/stuff")[1]))
195
        except Exception, exc:
196
            logging.warning("While mkdiring stuff: %s" % str(exc))
197
            pass
198
        try:
199
            svn.checkout(conf.svn_addr + login + "/info1",
200
                         common.studpath.url_to_local(login + "/info1")[1])
201
            os.system("chown -R %d:%d %s" \
202
                    % (details.unixid, details.unixid,
203
                       common.studpath.url_to_local(login + "/info1")[1]))
204
        except Exception, exc:
205
            logging.warning("While mkdiring info1: %s" % str(exc))
206
            pass
522 by drtomc
Add quite a lot of stuff to get usrmgt happening.
207
208
        # FIXME: should this be nicer?
209
        os.system("chown -R %d:%d %s" \
210
                % (details.unixid, details.unixid,
211
                   common.studpath.url_to_local(login)[1]))
212
213
571 by drtomc
usrmgt: improve the logging. Amazing what happens when you actually read
214
        logging.info("Enabling user")
473 by drtomc
usrmgt: progress the skeleton a bit further.
215
        db.update_user(login, state='enabled')
216
478 by mattgiuca
scripts/usrmgr-server: Renamed actions from dashes to underscores.
217
        return {"response": "okay"}
473 by drtomc
usrmgt: progress the skeleton a bit further.
218
219
    finally:
220
        db.close()
440 by drtomc
usrmgt: move the usrmgt sever to a better place.
221
676 by mattgiuca
usrmgt-server: Moved SVN checkout code from activate_me into a separate
222
def do_checkout(props):
223
    """Create the default contents of a user's jail by checking out from the
224
    repositories.
225
    If any directory already exists, just fail silently (so this is not a
226
    "wipe-and-checkout", merely a checkout if it failed or something).
227
       Expected properties:
228
        login       - the user name for the jail
229
                      STRING REQUIRED
230
       Return Value: None
231
    """
680 by mattgiuca
usrmgt-server: Desperate hack to make activate_me work again - do_checkout is
232
    # XXX / FIXME: This doesn't work - cannot get passwd
233
    # (activate_me creates passwd, other svn stuff gets it from jailconf - we
234
    # can't access either at this point).
676 by mattgiuca
usrmgt-server: Moved SVN checkout code from activate_me into a separate
235
236
    login = props['login']
677 by mattgiuca
userservice: Fix error message text.
237
    svn = pysvn.Client()
678 by mattgiuca
usrmgt-server: Added more missing stuff, resulting from the split to
238
    svn.callback_get_login = partial(get_login, login, passwd)
239
240
    if conf.svn_addr[-1] != '/':
241
        conf.svn_addr = conf.svn_addr + "/"
676 by mattgiuca
usrmgt-server: Moved SVN checkout code from activate_me into a separate
242
243
    # FIXME: </hack>
244
245
    logging.debug("Checking out directories in the jail")
246
    try:
247
        svn.checkout(conf.svn_addr + login + "/stuff",
248
                     common.studpath.url_to_local(login + "/stuff")[1])
249
        os.system("chown -R %d:%d %s" \
250
                % (details.unixid, details.unixid,
251
                   common.studpath.url_to_local(login + "/stuff")[1]))
252
    except Exception, exc:
253
        logging.warning("While mkdiring stuff: %s" % str(exc))
254
        pass
255
    try:
256
        svn.checkout(conf.svn_addr + login + "/info1",
257
                     common.studpath.url_to_local(login + "/info1")[1])
258
        os.system("chown -R %d:%d %s" \
259
                % (details.unixid, details.unixid,
260
                   common.studpath.url_to_local(login + "/info1")[1]))
261
    except Exception, exc:
262
        logging.warning("While mkdiring info1: %s" % str(exc))
263
        pass
264
265
    return {"response": "okay"}
266
452 by drtomc
usrmgt: checkpoint work on the usrmgt server.
267
actions = {
478 by mattgiuca
scripts/usrmgr-server: Renamed actions from dashes to underscores.
268
        'create_user':create_user,
551 by mattgiuca
userservice/usrmgt-server: Added update_user action to both.
269
        'update_user':update_user,
270
        'activate_user':activate_user,
676 by mattgiuca
usrmgt-server: Moved SVN checkout code from activate_me into a separate
271
        'do_checkout':do_checkout,
452 by drtomc
usrmgt: checkpoint work on the usrmgt server.
272
    }
273
684 by apeel
Added an initialisor to usrmgt-server which creates a PID file in /var/run. Needed for the /etc/init.d/ script.
274
def initializer():
275
    try:
276
        pidfile = open('/var/run/usrmgt-server.pid', 'w')
277
        pidfile.write('%d\n' % os.getpid())
278
        pidfile.close()
279
    except IOError, (errno, strerror):
280
        print "Couldn't write PID file. IO error(%s): %s" % (errno, strerror)
281
        sys.exit(1)
282
452 by drtomc
usrmgt: checkpoint work on the usrmgt server.
283
def dispatch(props):
571 by drtomc
usrmgt: improve the logging. Amazing what happens when you actually read
284
    logging.debug(repr(props))
452 by drtomc
usrmgt: checkpoint work on the usrmgt server.
285
    action = props.keys()[0]
286
    return actions[action](props[action])
287
440 by drtomc
usrmgt: move the usrmgt sever to a better place.
288
if __name__ == "__main__":
612 by mattgiuca
scripts/usrmgt-server: Now checks the length of its arguments and gives a
289
    if len(sys.argv) <3:
290
        print >>sys.stderr, "Usage: usrmgt-server <port> <magic>"
291
        sys.exit(1)
440 by drtomc
usrmgt: move the usrmgt sever to a better place.
292
    port = int(sys.argv[1])
293
    magic = sys.argv[2]
294
567 by drtomc
usrmgt: use proper logging.
295
    pid = os.getpid()
296
571 by drtomc
usrmgt: improve the logging. Amazing what happens when you actually read
297
    logging.basicConfig(filename="/var/log/usrmgt.log", level=logging.INFO)
298
    logging.info("Starting usrmgt server on port %d (pid = %d)" % (port, pid))
567 by drtomc
usrmgt: use proper logging.
299
684 by apeel
Added an initialisor to usrmgt-server which creates a PID file in /var/run. Needed for the /etc/init.d/ script.
300
    common.chat.start_server(port, magic, True, dispatch, initializer)