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