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

« back to all changes in this revision

Viewing changes to scripts/usrmgt-server

  • Committer: mattgiuca
  • Date: 2008-01-29 02:57:10 UTC
  • Revision ID: svn-v3-trunk0:2b9c9e99-6f39-0410-b283-7f802c844ae2:trunk:322
Added doc/setup - a setup guide specific to our configuration. This is the
result of my successfully configuring IVLE on a production server.

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
 
log = logging.FileHandler("/var/log/usrmgt.log")
38
 
 
39
 
def create_user(props):
40
 
    """Create the database record for the given user.
41
 
       Expected properties:
42
 
        login       - used as a unix login name and svn repository name.
43
 
                      STRING REQUIRED 
44
 
        unixid      - the unix uid under which execution will take place
45
 
                      on the behalf of the user. Don't use 0! If not specified
46
 
                      or None, one will be allocated from the configured
47
 
                      numeric range.
48
 
                      INT OPTIONAL
49
 
        password    - the clear-text password for the user. If this property is
50
 
                      absent or None, this is an indication that external
51
 
                      authentication should be used (i.e. LDAP).
52
 
                      STRING OPTIONAL
53
 
        email       - the user's email address.
54
 
                      STRING OPTIONAL
55
 
        nick        - the display name to use.
56
 
                      STRING REQUIRED
57
 
        fullname    - The name of the user for results and/or other official
58
 
                      purposes.
59
 
                      STRING REQUIRED
60
 
        rolenm      - The user's role. Must be one of "anyone", "student",
61
 
                      "tutor", "lecturer", "admin".
62
 
                      STRING/ENUM REQUIRED
63
 
        studentid   - If supplied and not None, the student id of the user for
64
 
                      results and/or other official purposes.
65
 
                      STRING OPTIONAL
66
 
       Return Value: the uid associated with the user. INT
67
 
    """
68
 
 
69
 
    if 'unixid' not in props or props['unixid'] is None:
70
 
        # For the time being, just choose a random unixid.
71
 
        # This may result in duplicates, but the unixid is essentially
72
 
        # a monitoring/logging convenience only. Oh, and dups could kill
73
 
        # each other. <sigh>
74
 
        props['unixid'] = random.randrange(5000,10000)
75
 
        # raise NotImplementedError, "No algorithm for creating uids yet!"
76
 
        # unixid = invent-uid
77
 
        # props['unixid'] = unixid
78
 
 
79
 
    common.makeuser.make_user_db(**props)
80
 
 
81
 
    return int(props['unixid'])
82
 
 
83
 
def update_user(props):
84
 
    """Create the database record for the given user.
85
 
       Expected properties:
86
 
        login       - user who is making the change (not necessarily the one
87
 
                      being updated).
88
 
        update      - dict of fields to be updated. The fields are all those
89
 
                      in the login table of the db.
90
 
                      'login' required.
91
 
                      Omitted fields will not be set.
92
 
    """
93
 
    update = props['update']
94
 
    # Note: "login" is special - it is not part of the kwargs to
95
 
    # db.update_user, but the first arg - used to find the user to update.
96
 
    # However it doesn't need any special treatment here.
97
 
 
98
 
    db = common.db.DB()
99
 
    db.update_user(**update)
100
 
    db.close()
101
 
 
102
 
def get_login(login, passwd, _realm, _login, _may_save):
103
 
    """Callback function used by pysvn for authentication.
104
 
    """
105
 
    log.debug("Getting password for %s (realm %s)" % (login, _realm))
106
 
    return (True, login, passwd, False)
107
 
 
108
 
def activate_user(props):
109
 
    """Create the on-disk stuff for the given user.
110
 
       Sets the state of the user in the db from pending to enabled.
111
 
       Expected properties:
112
 
        login       - the user name for the jail
113
 
                      STRING REQUIRED
114
 
       Return Value: None
115
 
    """
116
 
 
117
 
    login = props['login']
118
 
 
119
 
    db = common.db.DB()
120
 
 
121
 
    try:
122
 
 
123
 
        # FIXME: check we're pending
124
 
 
125
 
        details = db.get_user(login)
126
 
 
127
 
        # make svn config/auth
128
 
 
129
 
        log.debug("Creating repo")
130
 
        common.makeuser.make_svn_repo(login, throw_on_error=False)
131
 
        log.debug("Creating svn config")
132
 
        common.makeuser.make_svn_config(login, throw_on_error=False)
133
 
        log.debug("Creating svn auth")
134
 
        passwd = common.makeuser.make_svn_auth(login, throw_on_error=False)
135
 
        log.debug("passwd: %s" % passwd)
136
 
 
137
 
        svn = pysvn.Client()
138
 
        svn.callback_get_login = partial(get_login, login, passwd)
139
 
 
140
 
        if conf.svn_addr[-1] != '/':
141
 
            conf.svn_addr = conf.svn_addr + "/"
142
 
    
143
 
        # FIXME: This should be a loop over enrolements.
144
 
        #        We're not going to fix this now because it requires
145
 
        #        a large amount of admin console work to manage subject
146
 
        #        offerings.
147
 
        #        Instead, we're just going to use a single offering with
148
 
        #        a "short" name of "info1".
149
 
        log.debug("Creating /info1")
150
 
        try:
151
 
            svn.mkdir(conf.svn_addr + login + "/info1",
152
 
                      "Initial creation of work directory for Informatics 1")
153
 
        except Exception, exc:
154
 
            log.warning("While mkdiring info1: %s" % str(exc))
155
 
            pass
156
 
        log.debug("Creating /submissions")
157
 
        try:
158
 
            svn.mkdir(conf.svn_addr + login + "/submissions",
159
 
                      "Initial creation of submissions directory")
160
 
        except Exception, exc:
161
 
            log.warning("While mkdiring submissions: %s" % str(exc))
162
 
            pass
163
 
        log.debug("Creating /stuff")
164
 
        try:
165
 
            svn.mkdir(conf.svn_addr + login + "/stuff",
166
 
                      "Initial creation of directory for miscellania")
167
 
        except Exception, exc:
168
 
            log.warning("While mkdiring stuff: %s" % str(exc))
169
 
            pass
170
 
 
171
 
        log.debug("Creating jail")
172
 
        common.makeuser.make_jail(login, details.unixid)
173
 
 
174
 
        # FIXME: <hack>
175
 
 
176
 
        tcf_path = os.path.join(conf.jail_base, 'template/opt/ivle/lib/conf/conf.py')
177
 
        cf_path = os.path.join(conf.jail_base, login, 'opt/ivle/lib/conf/conf.py')
178
 
 
179
 
        os.remove(cf_path)
180
 
        cf = open(cf_path, "w")
181
 
        cf.write(open(tcf_path, "r").read())
182
 
        cf.write("# The login name for the owner of the jail\n")
183
 
        cf.write("login = %s\n" % repr(login))
184
 
        cf.write("\n")
185
 
        cf.write("# The subversion-only password for the owner of the jail\n")
186
 
        cf.write("svn_pass = %s\n" % repr(passwd))
187
 
        cf.close()
188
 
 
189
 
        # FIXME: </hack>
190
 
 
191
 
        log.debug("Checking out directories in the jail")
192
 
        try:
193
 
            svn.checkout(conf.svn_addr + login + "/stuff",
194
 
                         common.studpath.url_to_local(login + "/stuff")[1])
195
 
        except Exception, exc:
196
 
            log.warning("While mkdiring stuff: %s" % str(exc))
197
 
            pass
198
 
        try:
199
 
            svn.checkout(conf.svn_addr + login + "/submissions",
200
 
                         common.studpath.url_to_local(login + "/submissions")[1])
201
 
        except Exception, exc:
202
 
            log.warning("While mkdiring submissions: %s" % str(exc))
203
 
            pass
204
 
        try:
205
 
            svn.checkout(conf.svn_addr + login + "/info1",
206
 
                         common.studpath.url_to_local(login + "/info1")[1])
207
 
        except Exception, exc:
208
 
            log.warning("While mkdiring info1: %s" % str(exc))
209
 
            pass
210
 
 
211
 
        # FIXME: should this be nicer?
212
 
        os.system("chown -R %d:%d %s" \
213
 
                % (details.unixid, details.unixid,
214
 
                   common.studpath.url_to_local(login)[1]))
215
 
 
216
 
 
217
 
        log.info("Enabling user")
218
 
        db.update_user(login, state='enabled')
219
 
 
220
 
        return {"response": "okay"}
221
 
 
222
 
    finally:
223
 
        db.close()
224
 
 
225
 
actions = {
226
 
        'create_user':create_user,
227
 
        'update_user':update_user,
228
 
        'activate_user':activate_user,
229
 
    }
230
 
 
231
 
def dispatch(props):
232
 
    log.debug(repr(props))
233
 
    action = props.keys()[0]
234
 
    return actions[action](props[action])
235
 
 
236
 
if __name__ == "__main__":
237
 
    port = int(sys.argv[1])
238
 
    magic = sys.argv[2]
239
 
 
240
 
    pid = os.getpid()
241
 
 
242
 
    log.info("Starting usrmgt server on port %d (pid = %d)" % (port, pid))
243
 
 
244
 
    common.chat.start_server(port, magic, True, dispatch)