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

« back to all changes in this revision

Viewing changes to scripts/usrmgt-server

  • Committer: mattgiuca
  • Date: 2008-07-15 09:18:02 UTC
  • Revision ID: svn-v3-trunk0:2b9c9e99-6f39-0410-b283-7f802c844ae2:trunk:877
pulldown_subj/__init__.py: Added "enrol_user" function which pulls down a user
    and also enrols them in the database.
Added script enrolallusers.py which scriptulously performs automatic
enrolments of all users in the system, similar to remakeallusers.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
#!/usr/bin/python
2
2
 
3
3
import os
 
4
import pysvn
 
5
import subprocess
4
6
import sys
 
7
import urllib
 
8
from functools import partial
 
9
import traceback
5
10
import logging
 
11
import errno
6
12
 
7
13
import conf
8
14
import common.db
20
26
#           - create repository
21
27
#           - svn config
22
28
#           - svn auth
 
29
#       - Checkout repository as home directory
23
30
#       - /etc/passwd entry
24
31
#   - Disable a user's account
25
32
#   - Enable a user's account
28
35
#   - Rebuild svn auth file
29
36
#   - Rebuild passwd + push to nodes.
30
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, existing_login, _may_save):
 
102
    """Callback function used by pysvn for authentication.
 
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.
 
112
    """
 
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)
 
123
 
31
124
def activate_user(props):
32
125
    """Create the on-disk stuff for the given user.
33
126
       Sets the state of the user in the db from pending to enabled.
51
144
 
52
145
        # make svn config/auth
53
146
 
54
 
        repopath = os.path.join(conf.svn_repo_path, 'users', login)
55
 
        logging.debug("Creating user's Subversion repository")
56
 
        common.makeuser.make_svn_repo(repopath, throw_on_error=False)
57
 
 
58
 
        rebuild_svn_config(props)
59
 
 
60
 
        logging.debug("Adding Subversion authentication")
 
147
        logging.debug("Creating repo")
 
148
        common.makeuser.make_svn_repo(login, throw_on_error=False)
 
149
        logging.debug("Creating svn config")
 
150
        common.makeuser.make_svn_config(login, throw_on_error=False)
 
151
        logging.debug("Creating svn auth")
61
152
        passwd = common.makeuser.make_svn_auth(login, throw_on_error=False)
62
153
        logging.debug("passwd: %s" % passwd)
63
154
 
 
155
        svn = pysvn.Client()
 
156
        svn.callback_get_login = partial(get_login, login, passwd)
 
157
 
 
158
        if conf.svn_addr[-1] != '/':
 
159
            conf.svn_addr = conf.svn_addr + "/"
 
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".
 
167
        logging.debug("Creating /info1")
 
168
        try:
 
169
            svn.mkdir(conf.svn_addr + login + "/info1",
 
170
                      "Initial creation of work directory for Informatics 1")
 
171
        except Exception, exc:
 
172
            logging.warning("While mkdiring info1: %s" % str(exc))
 
173
            pass
 
174
        logging.debug("Creating /stuff")
 
175
        try:
 
176
            svn.mkdir(conf.svn_addr + login + "/stuff",
 
177
                      "Initial creation of directory for miscellania")
 
178
        except Exception, exc:
 
179
            logging.warning("While mkdiring stuff: %s" % str(exc))
 
180
            pass
 
181
 
64
182
        logging.debug("Creating jail")
65
183
        common.makeuser.make_jail(login, details.unixid, svn_pass=passwd)
66
184
 
 
185
        common.makeuser.mount_jail(login)
 
186
 
 
187
        do_checkout(props, svn_pass=passwd)
 
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
 
67
194
        logging.info("Enabling user")
68
195
        db.update_user(login, state='enabled')
69
196
 
72
199
    finally:
73
200
        db.close()
74
201
 
75
 
def rebuild_svn_config(props):
76
 
    """Rebuilds the svn config file
77
 
    Return value:
78
 
        response (okay, failure)
79
 
    """
80
 
    try:
81
 
        common.makeuser.rebuild_svn_config()
82
 
    except Exception, e:
83
 
        logging.warning('Rebuild of Subversion authorization config failed!')
84
 
        return{'response': 'failure', 'msg': repr(e)}
85
 
 
86
 
    return {'response': 'okay'}
87
 
 
88
 
def rebuild_svn_group_config(props):
89
 
    """Rebuilds the svn group config file
90
 
    Return value:
91
 
        response (okay, failure)
92
 
    """
93
 
    try:
94
 
        common.makeuser.rebuild_svn_group_config()
95
 
    except Exception, e:
96
 
        logging.warning(
97
 
            'Rebuild of Subversion group authorization config failed!')
98
 
        return{'response': 'failure', 'msg': repr(e)}
99
 
 
100
 
    return {'response': 'okay'}
101
 
 
102
 
def create_group_repository(props):
103
 
    """Creates on disk repository for the given group
104
 
    Expected properties:
105
 
        subj_short_name, year, semester, groupnm
106
 
    Return value:
107
 
        response (okay, failure)
108
 
    """
109
 
 
110
 
    subj_short_name = props['subj_short_name']
111
 
    year = props['year']
112
 
    semester = props['semester']
113
 
    groupnm = props['groupnm']
114
 
 
115
 
    namespace = "_".join([subj_short_name, year, semester, groupnm])
116
 
    repopath = os.path.join(conf.svn_repo_path, 'groups', namespace)
117
 
    logging.debug("Creating Subversion repository %s"%repopath)
118
 
    try:
119
 
        common.makeuser.make_svn_repo(repopath)
120
 
    except Exception, e:
121
 
        logging.error("Failed to create Subversion repository %s: %s"%
122
 
            (repopath,repr(e)))
123
 
        return {'response': 'failure', 'msg': repr(e)}
124
 
 
125
 
    return {'response': 'okay'}
 
202
def do_checkout(props, svn_pass=None):
 
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']
 
213
 
 
214
    db = common.db.DB()
 
215
    user = db.get_user(login)
 
216
    # If svn_pass isn't supplied, grab it from the DB
 
217
    if svn_pass is None:
 
218
        svn_pass = user.svn_pass
 
219
    db.close()
 
220
 
 
221
    svn = pysvn.Client()
 
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>
 
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" \
 
234
                % (user.unixid, user.unixid,
 
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" \
 
243
                % (user.unixid, user.unixid,
 
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
 
 
249
    # FIXME: </hack>
 
250
 
 
251
    return {"response": "okay"}
126
252
 
127
253
actions = {
 
254
        'create_user':create_user,
 
255
        'update_user':update_user,
128
256
        'activate_user':activate_user,
129
 
        'create_group_repository':create_group_repository,
130
 
        'rebuild_svn_config':rebuild_svn_config,
131
 
        'rebuild_svn_group_config':rebuild_svn_group_config,
 
257
        'do_checkout':do_checkout,
132
258
    }
133
259
 
134
260
def initializer():
146
272
    return actions[action](props[action])
147
273
 
148
274
if __name__ == "__main__":
 
275
    if len(sys.argv) <3:
 
276
        print >>sys.stderr, "Usage: usrmgt-server <port> <magic>"
 
277
        sys.exit(1)
 
278
    port = int(sys.argv[1])
 
279
    magic = sys.argv[2]
 
280
 
149
281
    pid = os.getpid()
150
282
 
151
283
    logging.basicConfig(filename="/var/log/usrmgt.log", level=logging.INFO)
152
 
    logging.info("Starting usrmgt server on port %d (pid = %d)" %
153
 
                 (conf.usrmgt_port, pid))
 
284
    logging.info("Starting usrmgt server on port %d (pid = %d)" % (port, pid))
154
285
 
155
 
    common.chat.start_server(conf.usrmgt_port, conf.usrmgt_magic, True, dispatch, initializer)
 
286
    common.chat.start_server(port, magic, True, dispatch, initializer)