~ubuntu-branches/debian/sid/openchange/sid

« back to all changes in this revision

Viewing changes to python/openchange/provision.py

  • Committer: Package Import Robot
  • Author(s): Jelmer Vernooij
  • Date: 2012-04-12 20:07:57 UTC
  • mfrom: (11 sid)
  • mto: This revision was merged to the branch mainline in revision 12.
  • Revision ID: package-import@ubuntu.com-20120412200757-k933d9trljmxj1l4
Tags: 1:1.0-4
* openchangeserver: Add dependency on openchangeproxy.
* Rebuild against newer version of Samba 4.
* Use dpkg-buildflags.
* Migrate to Git, update Vcs-Git header.
* Switch to debhelper 9.

Show diffs side-by-side

added added

removed removed

Lines of Context:
19
19
#
20
20
 
21
21
from base64 import b64encode
22
 
import os
 
22
import os,sys
 
23
import struct
23
24
import samba
24
25
from openchange import mailbox
25
 
from samba import Ldb
 
26
from samba import param, Ldb, dsdb, substitute_var, read_and_sub_file
26
27
from samba.samdb import SamDB
27
 
from samba.auth import system_session
28
 
from samba.provision import setup_add_ldif, setup_modify_ldif
29
 
from openchange.urlutils import openchangedb_url, openchangedb_mapistore_url, openchangedb_mapistore_dir, openchangedb_suffix_for_mapistore_url
 
28
import ldb
 
29
from ldb import (SCOPE_SUBTREE, SCOPE_BASE, FLAG_MOD_REPLACE, FLAG_MOD_ADD, FLAG_MOD_DELETE)
 
30
from samba.auth import system_session, admin_session
 
31
from samba.provision import (setup_add_ldif, setup_modify_ldif, setup_ldb,find_provision_key_parameters)
 
32
from samba.upgradehelpers import (get_paths, get_ldbs)
 
33
from openchange.urlutils import openchangedb_url
30
34
 
31
35
__docformat__ = 'restructuredText'
32
36
 
33
37
DEFAULTSITE = "Default-First-Site-Name"
34
38
FIRST_ORGANIZATION = "First Organization"
35
 
FIRST_ORGANIZATION_UNIT = "First Organization Unit"
 
39
FIRST_ORGANIZATION_UNIT = "First Administrative Group"
36
40
 
37
41
# This is a hack. Kind-of cute, but still a hack
38
42
def abstract():
135
139
 
136
140
def provision_schema(setup_path, names, lp, creds, reporter, ldif, msg):
137
141
    """Provision schema using LDIF specified file
138
 
 
139
142
    :param setup_path: Path to the setup directory.
140
143
    :param names: provision names object.
141
144
    :param lp: Loadparm context
147
150
 
148
151
    session_info = system_session()
149
152
 
150
 
    db = SamDB(url=lp.get("sam database"), session_info=session_info, 
 
153
    db = SamDB(url=lp.samdb_url(), session_info=session_info,
151
154
               credentials=creds, lp=lp)
152
155
 
153
156
    db.transaction_start()
154
157
 
155
158
    try:
156
159
        reporter.reportNextStep(msg)
157
 
        setup_add_ldif(db, setup_path(ldif), { 
 
160
        setup_add_ldif(db, setup_path(ldif), {
158
161
                "FIRSTORG": names.firstorg,
159
162
                "FIRSTORGDN": names.firstorgdn,
160
163
                "CONFIGDN": names.configdn,
172
175
    db.transaction_commit()
173
176
 
174
177
def modify_schema(setup_path, names, lp, creds, reporter, ldif, msg):
175
 
    """Modify schema using LDIF specified file
176
 
 
177
 
    :param setup_path: Path to the setup directory.
 
178
    """Modify schema using LDIF specified file                                                                                                                                                                          :param setup_path: Path to the setup directory.
178
179
    :param names: provision names object.
179
180
    :param lp: Loadparm context
180
181
    :param creds: Credentials Context
185
186
 
186
187
    session_info = system_session()
187
188
 
188
 
    db = SamDB(url=lp.get("sam database"), session_info=session_info, 
 
189
    db = SamDB(url=lp.samdb_url(), session_info=session_info,
189
190
               credentials=creds, lp=lp)
190
191
 
191
192
    db.transaction_start()
192
193
 
193
194
    try:
194
195
        reporter.reportNextStep(msg)
195
 
        setup_modify_ldif(db, setup_path(ldif), { 
 
196
        setup_modify_ldif(db, setup_path(ldif), {
196
197
                "SCHEMADN": names.schemadn,
197
198
                "CONFIGDN": names.configdn
198
199
                })
202
203
 
203
204
    db.transaction_commit()
204
205
 
 
206
 
205
207
def install_schemas(setup_path, names, lp, creds, reporter):
206
208
    """Install the OpenChange-specific schemas in the SAM LDAP database. 
207
209
    
213
215
    """
214
216
    session_info = system_session()
215
217
 
 
218
    lp.set("dsdb:schema update allowed", "yes")
 
219
 
216
220
    # Step 1. Extending the prefixmap attribute of the schema DN record
217
 
    db = SamDB(url=lp.get("sam database"), session_info=session_info,
 
221
    samdb = SamDB(url=lp.samdb_url(), session_info=session_info,
218
222
                  credentials=creds, lp=lp)
219
223
 
220
 
    prefixmap = open(setup_path("AD/prefixMap.txt"), 'r').read()
221
 
 
222
 
    db.transaction_start()
223
 
 
224
 
    try:
225
 
        reporter.reportNextStep("Register Exchange OIDs")
226
 
        setup_modify_ldif(db,
227
 
                          setup_path("AD/provision_schema_basedn_modify.ldif"), {
228
 
                "SCHEMADN": names.schemadn,
229
 
                "NETBIOSNAME": names.netbiosname,
230
 
                "DEFAULTSITE": names.sitename,
231
 
                "CONFIGDN": names.configdn,
232
 
                "SERVERDN": names.serverdn,
233
 
                "PREFIXMAP_B64": b64encode(prefixmap)
234
 
                })
235
 
    except:
236
 
        db.transaction_cancel()
237
 
        raise
238
 
 
239
 
    db.transaction_commit()
 
224
    schemadn = str(names.schemadn)
 
225
    current = samdb.search(expression="objectClass=*", base=schemadn, 
 
226
                           scope=SCOPE_SUBTREE)
 
227
    
 
228
 
 
229
    schema_ldif = ""
 
230
    prefixmap_data = ""
 
231
    for ent in current:
 
232
        schema_ldif += samdb.write_ldif(ent, ldb.CHANGETYPE_NONE)
 
233
 
 
234
    prefixmap_data = open(setup_path("AD/prefixMap.txt"), 'r').read()
 
235
    prefixmap_data = b64encode(prefixmap_data)
 
236
 
 
237
    # We don't actually add this ldif, just parse it
 
238
    prefixmap_ldif = "dn: %s\nprefixMap:: %s\n\n" % (schemadn, prefixmap_data)
 
239
    reporter.reportNextStep("Register Exchange OIDs")
 
240
    dsdb._dsdb_set_schema_from_ldif(samdb, prefixmap_ldif, schema_ldif, schemadn)
240
241
 
241
242
    provision_schema(setup_path, names, lp, creds, reporter, "AD/oc_provision_schema_attributes.ldif", "Add Exchange attributes to Samba schema")
242
243
    provision_schema(setup_path, names, lp, creds, reporter, "AD/oc_provision_schema_auxiliary_class.ldif", "Add Exchange auxiliary classes to Samba schema")
251
252
    provision_schema(setup_path, names, lp, creds, reporter, "AD/oc_provision_configuration.ldif", "Exchange Samba with Exchange configuration objects")
252
253
    print "[SUCCESS] Done!"
253
254
 
254
 
def newmailbox(lp, username, firstorg, firstou, backend):
255
 
    names = guess_names_from_smbconf(lp, firstorg, firstou)
256
 
 
257
 
    db = mailbox.OpenChangeDB(openchangedb_url(lp))
258
 
 
259
 
    # Step 1. Retrieve current FID index
260
 
    GlobalCount = db.get_message_GlobalCount(names.netbiosname)
261
 
    ReplicaID = db.get_message_ReplicaID(names.netbiosname)
262
 
 
263
 
    print "[+] Mailbox for '%s'" % (username)
264
 
    print "==================" + "=" * len(username)
265
 
    print "* GlobalCount (0x%x) and ReplicaID (0x%x)" % (GlobalCount, ReplicaID)
266
 
 
267
 
    # Step 2. Check if the user already exists
268
 
    assert not db.user_exists(names.netbiosname, username)
269
 
 
270
 
    # Step 3. Create a default mapistore content repository for this user
271
 
    db.add_storage_dir(mapistoreURL=openchangedb_mapistore_dir(lp), username=username)
272
 
    print "* Mapistore content repository created: %s" % os.path.join(openchangedb_mapistore_dir(lp), username)
273
 
 
274
 
    # Step 4. Create the user object
275
 
    retdn = db.add_mailbox_user(names.ocfirstorgdn, username=username)
276
 
    print "* User object created: %s" % (retdn)
277
 
 
278
 
    # Step 5. Create system mailbox folders for this user
279
 
    print "* Adding System Folders"
280
 
 
281
 
    system_folders = ({
282
 
        "Deferred Actions": ({}, 2),
283
 
        "Spooler Queue": ({}, 3),
284
 
        "To-Do Search": ({}, 4),
285
 
        "IPM Subtree": ({
286
 
            "Inbox": ({}, 6),
287
 
            "Outbox": ({}, 7),
288
 
            "Sent Items": ({}, 8),
289
 
            "Deleted Items": ({}, 9),
290
 
        }, 5),
291
 
        "Common Views": ({}, 10),
292
 
        "Schedule": ({}, 11),
293
 
        "Search": ({}, 12),
294
 
        "Views": ({}, 13),
295
 
        "Shortcuts": ({}, 14),
296
 
        "Reminders": ({}, 15),
297
 
    }, 1)
298
 
 
299
 
    fids = {}
300
 
    def add_folder(parent_fid, path, children, SystemIdx):
301
 
        name = path[-1]
302
 
 
303
 
        GlobalCount = db.get_message_GlobalCount(names.netbiosname)
304
 
        ReplicaID = db.get_message_ReplicaID(names.netbiosname)
305
 
        url = openchangedb_mapistore_url(lp, backend)
306
 
 
307
 
        fid = db.add_mailbox_root_folder(names.ocfirstorgdn, 
308
 
            username=username, foldername=name,
309
 
            parentfolder=parent_fid, GlobalCount=GlobalCount, 
310
 
            ReplicaID=ReplicaID, SystemIdx=SystemIdx, 
311
 
            mapistoreURL=url,
312
 
            mapistoreSuffix=openchangedb_suffix_for_mapistore_url(url))
313
 
 
314
 
        GlobalCount += 1
315
 
        db.set_message_GlobalCount(names.netbiosname, GlobalCount=GlobalCount)
316
 
 
317
 
        fids[path] = fid
318
 
 
319
 
        print "\t* %-40s: %s" % (name, fid)
320
 
        for name, grandchildren in children.iteritems():
321
 
            add_folder(fid, path + (name,), grandchildren[0], grandchildren[1])
322
 
 
323
 
    add_folder(0, ("Mailbox Root",), system_folders[0], system_folders[1])
324
 
 
325
 
    # Step 6. Add special folders
326
 
    print "* Adding Special Folders:"
327
 
    special_folders = [
328
 
        (("Mailbox Root", "IPM Subtree"), "Calendar",   "IPF.Appointment",  "PidTagIpmAppointmentEntryId"),
329
 
        (("Mailbox Root", "IPM Subtree"), "Contacts",   "IPF.Contact",      "PidTagIpmContactEntryId"),
330
 
        (("Mailbox Root", "IPM Subtree"), "Journal",    "IPF.Journal",      "PidTagIpmJournalEntryId"),
331
 
        (("Mailbox Root", "IPM Subtree"), "Notes",      "IPF.StickyNote",   "PidTagIpmNoteEntryId"),
332
 
        (("Mailbox Root", "IPM Subtree"), "Tasks",      "IPF.Task",         "PidTagIpmTaskEntryId"),
333
 
        (("Mailbox Root", "IPM Subtree"), "Drafts",     "IPF.Note",         "PidTagIpmDraftsEntryId")
334
 
        ]
335
 
 
336
 
    fid_inbox = fids[("Mailbox Root", "IPM Subtree", "Inbox")]
337
 
    fid_reminders = fids[("Mailbox Root", "Reminders")]
338
 
    fid_mailbox = fids[("Mailbox Root",)]
339
 
    for path, foldername, containerclass, pidtag in special_folders:
340
 
        GlobalCount = db.get_message_GlobalCount(names.netbiosname)
341
 
        ReplicaID = db.get_message_ReplicaID(names.netbiosname)
342
 
        url = openchangedb_mapistore_url(lp, backend)
343
 
        fid = db.add_mailbox_special_folder(username, fids[path], fid_inbox, foldername, 
344
 
                                            containerclass, GlobalCount, ReplicaID, 
345
 
                                            url, openchangedb_suffix_for_mapistore_url(url))
346
 
        db.add_folder_property(fid_inbox, pidtag, fid)
347
 
        db.add_folder_property(fid_mailbox, pidtag, fid)
348
 
        GlobalCount += 1
349
 
        db.set_message_GlobalCount(names.netbiosname, GlobalCount=GlobalCount)
350
 
        print "\t* %-40s: %s (%s)" % (foldername, fid, containerclass)
351
 
 
352
 
    # Step 7. Set default receive folders
353
 
    print "* Adding default Receive Folders:"
354
 
    receive_folders = [
355
 
        (("Mailbox Root", "IPM Subtree", "Inbox"), "All"),
356
 
        (("Mailbox Root", "IPM Subtree", "Inbox"), "IPM"),
357
 
        (("Mailbox Root", "IPM Subtree", "Inbox"), "Report.IPM"),
358
 
        (("Mailbox Root", "IPM Subtree", "Inbox"), "IPM.Note"),
359
 
        (("Mailbox Root", "IPM Subtree",), "IPC")
360
 
        ]
361
 
    
362
 
    for path, messageclass in receive_folders:
363
 
        print "\t* %-40s Message Class added to %s" % (messageclass, fids[path])
364
 
        db.set_receive_folder(username, names.ocfirstorgdn, fids[path], 
365
 
                              messageclass)
366
 
 
367
 
    # Step 8. Set additional properties on Inbox
368
 
    print "* Adding additional default properties to Inbox"
369
 
    db.add_folder_property(fid_inbox, "PidTagContentCount", "0")
370
 
    db.add_folder_property(fid_inbox, "PidTagContentUnreadCount", "0")
371
 
    db.add_folder_property(fid_inbox, "PidTagSubFolders", "FALSE")
372
 
 
373
 
    print "* Adding additional default properties to Reminders"
374
 
    db.add_folder_property(fid_reminders, "PidTagContainerClass", "Outlook.Reminder");
375
 
    db.add_folder_property(fid_inbox, "PidTagRemindersOnlineEntryId", fid_reminders);
376
 
    db.add_folder_property(fid_mailbox, "PidTagRemindersOnlineEntryId", fid_reminders);
377
 
 
378
 
    GlobalCount = db.get_message_GlobalCount(names.netbiosname)
379
 
    print "* GlobalCount (0x%x)" % GlobalCount
380
 
 
381
 
 
382
255
def newuser(lp, creds, username=None):
383
256
    """extend user record with OpenChange settings.
384
257
    
389
262
 
390
263
    names = guess_names_from_smbconf(lp, None, None)
391
264
 
392
 
    db = Ldb(url=os.path.join(lp.get("private dir"), lp.get("sam database")), 
393
 
             session_info=system_session(), credentials=creds, lp=lp)
 
265
    db = Ldb(url=lp.samdb_url(), session_info=system_session(), 
 
266
             credentials=creds, lp=lp)
394
267
 
395
268
    user_dn = "CN=%s,CN=Users,%s" % (username, names.domaindn)
396
269
 
405
278
mailNickname: %s
406
279
add: homeMDB
407
280
homeMDB: CN=Mailbox Store (%s),CN=First Storage Group,CN=InformationStore,CN=%s,CN=Servers,CN=First Administrative Group,CN=Administrative Groups,CN=%s,CN=Microsoft Exchange,CN=Services,CN=Configuration,%s
 
281
add: homeMTA
 
282
homeMTA: CN=Mailbox Store (%s),CN=First Storage Group,CN=InformationStore,CN=%s,CN=Servers,CN=First Administrative Group,CN=Administrative Groups,CN=%s,CN=Microsoft Exchange,CN=Services,CN=Configuration,%s
408
283
add: legacyExchangeDN
409
284
legacyExchangeDN: /o=%s/ou=First Administrative Group/cn=Recipients/cn=%s
410
285
add: proxyAddresses
 
286
proxyAddresses: =EX:/o=%s/ou=First Administrative Group/cn=Recipients/cn=%s
411
287
proxyAddresses: smtp:postmaster@%s
412
288
proxyAddresses: X400:c=US;a= ;p=First Organizati;o=Exchange;s=%s
413
289
proxyAddresses: SMTP:%s@%s
414
290
replace: msExchUserAccountControl
415
291
msExchUserAccountControl: 0
416
 
""" % (user_dn, username, username, names.netbiosname, names.netbiosname, names.firstorg, names.domaindn, names.firstorg, username, names.dnsdomain, username, username, names.dnsdomain)
 
292
""" % (user_dn, username, username, names.netbiosname, names.netbiosname, names.firstorg, names.domaindn, names.netbiosname, names.netbiosname, names.firstorg, names.domaindn, names.firstorg, username, names.firstorg, username, names.dnsdomain, username, username, names.dnsdomain)
417
293
    db.modify_ldif(extended_user)
418
294
 
419
295
    print "[+] User %s extended and enabled" % username
430
306
 
431
307
    names = guess_names_from_smbconf(lp, None, None)
432
308
 
433
 
    db = Ldb(url=os.path.join(lp.get("private dir"), lp.get("sam database")), 
 
309
    db = Ldb(url=os.path.join(lp.get("private dir"), lp.samdb_url()), 
434
310
             session_info=system_session(), credentials=creds, lp=lp)
435
311
 
436
312
    user_dn = "CN=%s,CN=Users,%s" % (username, names.domaindn)
484
360
    openchange_ldb = mailbox.OpenChangeDB(openchangedb_url(lp))
485
361
    openchange_ldb.setup()
486
362
 
 
363
    print "Adding root DSE"
487
364
    openchange_ldb.add_rootDSE(names.ocserverdn, names.firstorg, names.firstou)
488
365
 
489
366
    # Add a server object
490
367
    # It is responsible for holding the GlobalCount identifier (48 bytes)
491
368
    # and the Replica identifier
492
 
    openchange_ldb.add_server(names.ocserverdn, names.netbiosname, 
493
 
        names.firstorg, names.firstou)
 
369
    openchange_ldb.add_server(names.ocserverdn, names.netbiosname, names.firstorg, names.firstou)
494
370
 
495
 
    mapistoreURL = os.path.join( openchangedb_mapistore_url(lp, mapistore), "publicfolders")
496
371
    print "[+] Public Folders"
497
372
    print "==================="
498
 
    openchange_ldb.add_public_folders(names, mapistoreURL)
 
373
    openchange_ldb.add_public_folders(names)
499
374
 
500
375
def find_setup_dir():
501
376
    """Find the setup directory used by provision."""