~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
783 by mattgiuca
usrmgt-server, fileservice_lib/action.py: Fixed SVN get_login callback.
101
def get_login(login, passwd, realm, existing_login, _may_save):
522 by drtomc
Add quite a lot of stuff to get usrmgt happening.
102
    """Callback function used by pysvn for authentication.
783 by mattgiuca
usrmgt-server, fileservice_lib/action.py: Fixed SVN get_login callback.
103
    login, passwd: Credentials of the user attempting to log in.
104
        passwd in clear (this should be the user's svn_pass, a
105
        randomly-generated permanent password for this user, not their main
106
        IVLE password).
107
    realm, existing_login, _may_save: The 3 arguments passed by pysvn to
108
        callback_get_login.
109
        The following has been determined empirically, not from docs:
110
        existing_login will be the name of the user who owns the process on
111
        the first attempt, "" on subsequent attempts. We use this fact.
522 by drtomc
Add quite a lot of stuff to get usrmgt happening.
112
    """
783 by mattgiuca
usrmgt-server, fileservice_lib/action.py: Fixed SVN get_login callback.
113
    logging.debug("Getting password for %s (realm %s)" % (login, realm))
114
    # Only provide credentials on the _first_ attempt.
115
    # If we're being asked again, then it means the credentials failed for
116
    # some reason and we should just fail. (This is not desirable, but it's
117
    # better than being asked an infinite number of times).
118
    if existing_login == "":
119
        logging.warning("Could not authenticate SVN for %s" % login)
120
        return (False, login, passwd, False)
121
    else:
122
        return (True, login, passwd, False)
522 by drtomc
Add quite a lot of stuff to get usrmgt happening.
123
473 by drtomc
usrmgt: progress the skeleton a bit further.
124
def activate_user(props):
125
    """Create the on-disk stuff for the given user.
126
       Sets the state of the user in the db from pending to enabled.
454 by drtomc
usrmgt-server: more work.
127
       Expected properties:
473 by drtomc
usrmgt: progress the skeleton a bit further.
128
        login       - the user name for the jail
454 by drtomc
usrmgt-server: more work.
129
                      STRING REQUIRED
456 by drtomc
usrmgt-server: a bit more work.
130
       Return Value: None
454 by drtomc
usrmgt-server: more work.
131
    """
456 by drtomc
usrmgt-server: a bit more work.
132
813 by William Grant
Merge jails-redux branch. We now use aufs rather than hardlinking tens
133
    os.umask(0022) # Bad, but start_server sets it worse.
134
473 by drtomc
usrmgt: progress the skeleton a bit further.
135
    login = props['login']
136
137
    db = common.db.DB()
138
139
    try:
140
141
        # FIXME: check we're pending
142
143
        details = db.get_user(login)
144
522 by drtomc
Add quite a lot of stuff to get usrmgt happening.
145
        # make svn config/auth
146
571 by drtomc
usrmgt: improve the logging. Amazing what happens when you actually read
147
        logging.debug("Creating repo")
522 by drtomc
Add quite a lot of stuff to get usrmgt happening.
148
        common.makeuser.make_svn_repo(login, throw_on_error=False)
571 by drtomc
usrmgt: improve the logging. Amazing what happens when you actually read
149
        logging.debug("Creating svn config")
522 by drtomc
Add quite a lot of stuff to get usrmgt happening.
150
        common.makeuser.make_svn_config(login, throw_on_error=False)
571 by drtomc
usrmgt: improve the logging. Amazing what happens when you actually read
151
        logging.debug("Creating svn auth")
522 by drtomc
Add quite a lot of stuff to get usrmgt happening.
152
        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
153
        logging.debug("passwd: %s" % passwd)
522 by drtomc
Add quite a lot of stuff to get usrmgt happening.
154
155
        svn = pysvn.Client()
156
        svn.callback_get_login = partial(get_login, login, passwd)
528 by drtomc
usrmgt-server: robustify svn url handling a bit.
157
158
        if conf.svn_addr[-1] != '/':
159
            conf.svn_addr = conf.svn_addr + "/"
522 by drtomc
Add quite a lot of stuff to get usrmgt happening.
160
    
161
        # FIXME: This should be a loop over enrolements.
162
        #        We're not going to fix this now because it requires
163
        #        a large amount of admin console work to manage subject
164
        #        offerings.
165
        #        Instead, we're just going to use a single offering with
166
        #        a "short" name of "info1".
571 by drtomc
usrmgt: improve the logging. Amazing what happens when you actually read
167
        logging.debug("Creating /info1")
522 by drtomc
Add quite a lot of stuff to get usrmgt happening.
168
        try:
169
            svn.mkdir(conf.svn_addr + login + "/info1",
170
                      "Initial creation of work directory for Informatics 1")
171
        except Exception, exc:
571 by drtomc
usrmgt: improve the logging. Amazing what happens when you actually read
172
            logging.warning("While mkdiring info1: %s" % str(exc))
522 by drtomc
Add quite a lot of stuff to get usrmgt happening.
173
            pass
571 by drtomc
usrmgt: improve the logging. Amazing what happens when you actually read
174
        logging.debug("Creating /stuff")
522 by drtomc
Add quite a lot of stuff to get usrmgt happening.
175
        try:
176
            svn.mkdir(conf.svn_addr + login + "/stuff",
177
                      "Initial creation of directory for miscellania")
178
        except Exception, exc:
571 by drtomc
usrmgt: improve the logging. Amazing what happens when you actually read
179
            logging.warning("While mkdiring stuff: %s" % str(exc))
522 by drtomc
Add quite a lot of stuff to get usrmgt happening.
180
            pass
181
571 by drtomc
usrmgt: improve the logging. Amazing what happens when you actually read
182
        logging.debug("Creating jail")
767 by mattgiuca
Moved code to create user's jail version of conf.py from usrmgt server
183
        common.makeuser.make_jail(login, details.unixid, svn_pass=passwd)
522 by drtomc
Add quite a lot of stuff to get usrmgt happening.
184
813 by William Grant
Merge jails-redux branch. We now use aufs rather than hardlinking tens
185
        common.makeuser.mount_jail(login)
186
768 by mattgiuca
usrmgt-server: Made do_checkout work!
187
        do_checkout(props, svn_pass=passwd)
522 by drtomc
Add quite a lot of stuff to get usrmgt happening.
188
189
        # FIXME: should this be nicer?
190
        os.system("chown -R %d:%d %s" \
191
                % (details.unixid, details.unixid,
192
                   common.studpath.url_to_local(login)[1]))
193
571 by drtomc
usrmgt: improve the logging. Amazing what happens when you actually read
194
        logging.info("Enabling user")
473 by drtomc
usrmgt: progress the skeleton a bit further.
195
        db.update_user(login, state='enabled')
196
478 by mattgiuca
scripts/usrmgr-server: Renamed actions from dashes to underscores.
197
        return {"response": "okay"}
473 by drtomc
usrmgt: progress the skeleton a bit further.
198
199
    finally:
200
        db.close()
440 by drtomc
usrmgt: move the usrmgt sever to a better place.
201
768 by mattgiuca
usrmgt-server: Made do_checkout work!
202
def do_checkout(props, svn_pass=None):
676 by mattgiuca
usrmgt-server: Moved SVN checkout code from activate_me into a separate
203
    """Create the default contents of a user's jail by checking out from the
204
    repositories.
205
    If any directory already exists, just fail silently (so this is not a
206
    "wipe-and-checkout", merely a checkout if it failed or something).
207
       Expected properties:
208
        login       - the user name for the jail
209
                      STRING REQUIRED
210
       Return Value: None
211
    """
212
    login = props['login']
768 by mattgiuca
usrmgt-server: Made do_checkout work!
213
813 by William Grant
Merge jails-redux branch. We now use aufs rather than hardlinking tens
214
    db = common.db.DB()
215
    user = db.get_user(login)
768 by mattgiuca
usrmgt-server: Made do_checkout work!
216
    # If svn_pass isn't supplied, grab it from the DB
217
    if svn_pass is None:
218
        svn_pass = user.svn_pass
813 by William Grant
Merge jails-redux branch. We now use aufs rather than hardlinking tens
219
    db.close()
768 by mattgiuca
usrmgt-server: Made do_checkout work!
220
677 by mattgiuca
userservice: Fix error message text.
221
    svn = pysvn.Client()
768 by mattgiuca
usrmgt-server: Made do_checkout work!
222
    svn.callback_get_login = partial(get_login, login, svn_pass)
223
224
    if conf.svn_addr[-1] != os.sep:
225
        conf.svn_addr += os.sep
226
227
    # FIXME: <hack>
676 by mattgiuca
usrmgt-server: Moved SVN checkout code from activate_me into a separate
228
229
    logging.debug("Checking out directories in the jail")
230
    try:
231
        svn.checkout(conf.svn_addr + login + "/stuff",
232
                     common.studpath.url_to_local(login + "/stuff")[1])
233
        os.system("chown -R %d:%d %s" \
768 by mattgiuca
usrmgt-server: Made do_checkout work!
234
                % (user.unixid, user.unixid,
676 by mattgiuca
usrmgt-server: Moved SVN checkout code from activate_me into a separate
235
                   common.studpath.url_to_local(login + "/stuff")[1]))
236
    except Exception, exc:
237
        logging.warning("While mkdiring stuff: %s" % str(exc))
238
        pass
239
    try:
240
        svn.checkout(conf.svn_addr + login + "/info1",
241
                     common.studpath.url_to_local(login + "/info1")[1])
242
        os.system("chown -R %d:%d %s" \
768 by mattgiuca
usrmgt-server: Made do_checkout work!
243
                % (user.unixid, user.unixid,
676 by mattgiuca
usrmgt-server: Moved SVN checkout code from activate_me into a separate
244
                   common.studpath.url_to_local(login + "/info1")[1]))
245
    except Exception, exc:
246
        logging.warning("While mkdiring info1: %s" % str(exc))
247
        pass
248
768 by mattgiuca
usrmgt-server: Made do_checkout work!
249
    # FIXME: </hack>
250
676 by mattgiuca
usrmgt-server: Moved SVN checkout code from activate_me into a separate
251
    return {"response": "okay"}
252
452 by drtomc
usrmgt: checkpoint work on the usrmgt server.
253
actions = {
478 by mattgiuca
scripts/usrmgr-server: Renamed actions from dashes to underscores.
254
        'create_user':create_user,
551 by mattgiuca
userservice/usrmgt-server: Added update_user action to both.
255
        'update_user':update_user,
256
        'activate_user':activate_user,
676 by mattgiuca
usrmgt-server: Moved SVN checkout code from activate_me into a separate
257
        'do_checkout':do_checkout,
452 by drtomc
usrmgt: checkpoint work on the usrmgt server.
258
    }
259
684 by apeel
Added an initialisor to usrmgt-server which creates a PID file in /var/run. Needed for the /etc/init.d/ script.
260
def initializer():
261
    try:
262
        pidfile = open('/var/run/usrmgt-server.pid', 'w')
263
        pidfile.write('%d\n' % os.getpid())
264
        pidfile.close()
265
    except IOError, (errno, strerror):
266
        print "Couldn't write PID file. IO error(%s): %s" % (errno, strerror)
267
        sys.exit(1)
268
452 by drtomc
usrmgt: checkpoint work on the usrmgt server.
269
def dispatch(props):
571 by drtomc
usrmgt: improve the logging. Amazing what happens when you actually read
270
    logging.debug(repr(props))
452 by drtomc
usrmgt: checkpoint work on the usrmgt server.
271
    action = props.keys()[0]
272
    return actions[action](props[action])
273
440 by drtomc
usrmgt: move the usrmgt sever to a better place.
274
if __name__ == "__main__":
612 by mattgiuca
scripts/usrmgt-server: Now checks the length of its arguments and gives a
275
    if len(sys.argv) <3:
276
        print >>sys.stderr, "Usage: usrmgt-server <port> <magic>"
277
        sys.exit(1)
440 by drtomc
usrmgt: move the usrmgt sever to a better place.
278
    port = int(sys.argv[1])
279
    magic = sys.argv[2]
280
567 by drtomc
usrmgt: use proper logging.
281
    pid = os.getpid()
282
764 by mattgiuca
usrmgt-server: Revert accidental change in previous commit: Logging level set
283
    logging.basicConfig(filename="/var/log/usrmgt.log", level=logging.INFO)
571 by drtomc
usrmgt: improve the logging. Amazing what happens when you actually read
284
    logging.info("Starting usrmgt server on port %d (pid = %d)" % (port, pid))
567 by drtomc
usrmgt: use proper logging.
285
684 by apeel
Added an initialisor to usrmgt-server which creates a PID file in /var/run. Needed for the /etc/init.d/ script.
286
    common.chat.start_server(port, magic, True, dispatch, initializer)