Start to rework provision for LDAP backends
[samba.git] / source4 / scripting / python / samba / provision.py
index d30eaf3d7fdd376669feb3f9d1b4b1f6cdc55683..b140071f41f5307680d453b42a345e1c222eb743 100644 (file)
@@ -59,6 +59,7 @@ class ProvisionPaths:
         self.hkpd = None
         self.hkpt = None
         self.samdb = None
+        self.idmapdb = None
         self.secrets = None
         self.keytab = None
         self.dns_keytab = None
@@ -202,6 +203,7 @@ def provision_paths_from_lp(lp, dnsdomain):
 
     paths.shareconf = os.path.join(private_dir, "share.ldb")
     paths.samdb = os.path.join(private_dir, lp.get("sam database") or "samdb.ldb")
+    paths.idmapdb = os.path.join(private_dir, lp.get("idmap database") or "idmap.ldb")
     paths.secrets = os.path.join(private_dir, lp.get("secrets database") or "secrets.ldb")
     paths.templates = os.path.join(private_dir, "templates.ldb")
     paths.dns = os.path.join(private_dir, dnsdomain + ".zone")
@@ -277,8 +279,6 @@ def setup_samdb_partitions(samdb_path, setup_path, message, lp, session_info,
     
     Alternatively, provision() may call this, and then populate the database.
     
-    :param erase: Remove the existing data present in the database.
-     
     :note: This will wipe the Sam Database!
     
     :note: This function always removes the local SAM LDB file. The erase 
@@ -287,10 +287,15 @@ def setup_samdb_partitions(samdb_path, setup_path, message, lp, session_info,
     """
     assert session_info is not None
 
-    if os.path.exists(samdb_path):
+    samdb = SamDB(samdb_path, session_info=session_info, 
+                  credentials=credentials, lp=lp)
+
+    # Wipes the database
+    try:
+        samdb.erase()
+    except:
         os.unlink(samdb_path)
 
-    # Also wipes the database
     samdb = SamDB(samdb_path, session_info=session_info, 
                   credentials=credentials, lp=lp)
 
@@ -311,9 +316,9 @@ def setup_samdb_partitions(samdb_path, setup_path, message, lp, session_info,
                     "server_sort",
                     "extended_dn",
                     "asq",
-                    "samldb",
                     "rdn_name",
                     "objectclass",
+                    "samldb",
                     "kludge_acl",
                     "operational"]
     tdb_modules_list = [
@@ -335,13 +340,22 @@ def setup_samdb_partitions(samdb_path, setup_path, message, lp, session_info,
        schemadn_ldb = ldap_backend
        
     if ldap_backend_type == "fedora-ds":
-        backend_modules = ["nsuniqueid","paged_searches"]
+        backend_modules = ["nsuniqueid", "paged_searches"]
+        # We can handle linked attributes here, as we don't have directory-side subtree operations
+        tdb_modules_list = ["linked_attributes"]
     elif ldap_backend_type == "openldap":
-        backend_modules = ["normalise","entryuuid","paged_searches"]
+        backend_modules = ["normalise", "entryuuid", "paged_searches"]
+        # OpenLDAP handles subtree renames, so we don't want to do any of these things
+        tdb_modules_list = None
     elif serverrole == "domain controller":
         backend_modules = ["repl_meta_data"]
     else:
         backend_modules = ["objectguid"]
+
+    if tdb_modules_list is None:
+        tdb_modules_list_as_string = ""
+    else:
+        tdb_modules_list_as_string = ","+",".join(tdb_modules_list)
         
     samdb.transaction_start()
     try:
@@ -357,7 +371,7 @@ def setup_samdb_partitions(samdb_path, setup_path, message, lp, session_info,
                 "CONFIGDN_MOD": "naming_fsmo,instancetype",
                 "DOMAINDN_MOD": "pdc_fsmo,password_hash,instancetype",
                 "MODULES_LIST": ",".join(modules_list),
-                "TDB_MODULES_LIST": ","+",".join(tdb_modules_list),
+                "TDB_MODULES_LIST": tdb_modules_list_as_string,
                 "MODULES_LIST2": ",".join(modules_list2),
                 "BACKEND_MOD": ",".join(backend_modules),
         })
@@ -471,6 +485,24 @@ def setup_registry(path, setup_path, session_info, credentials, lp):
     assert os.path.exists(provision_reg)
     reg.diff_apply(provision_reg)
 
+def setup_idmapdb(path, setup_path, session_info, credentials, lp):
+    """Setup the idmap database.
+
+    :param path: path to the idmap database
+    :param setup_path: Function that returns a path to a setup file
+    :param session_info: Session information
+    :param credentials: Credentials
+    :param lp: Loadparm context
+    """
+    if os.path.exists(path):
+        os.unlink(path)
+
+    idmap_ldb = Ldb(path, session_info=session_info, credentials=credentials,
+                    lp=lp)
+
+    idmap_ldb.erase()
+    idmap_ldb.load_ldif_file_add(setup_path("idmap_init.ldif"))
+    return idmap_ldb
 
 def setup_samdb_rootdse(samdb, setup_path, schemadn, domaindn, hostname, 
                         dnsdomain, realm, rootdn, configdn, netbiosname,
@@ -527,7 +559,7 @@ def setup_self_join(samdb, configdn, schemadn, domaindn,
 
 def setup_samdb(path, setup_path, session_info, credentials, lp, 
                 schemadn, configdn, domaindn, dnsdomain, realm, 
-                netbiosname, message, hostname, rootdn, erase, 
+                netbiosname, message, hostname, rootdn, 
                 domainsid, aci, domainguid, policyguid, 
                 domainname, fill, adminpass, krbtgtpass, 
                 machinepass, hostguid, invocationid, dnspass,
@@ -540,6 +572,8 @@ def setup_samdb(path, setup_path, session_info, credentials, lp,
 
     assert serverrole in ("domain controller", "member server")
 
+    erase = (fill != FILL_DRS)    
+
     # Also wipes the database
     setup_samdb_partitions(path, setup_path, schemadn=schemadn, configdn=configdn, 
                            domaindn=domaindn, message=message, lp=lp,
@@ -695,6 +729,7 @@ def setup_samdb(path, setup_path, session_info, credentials, lp,
     samdb.transaction_commit()
     return samdb
 
+
 FILL_FULL = "FULL"
 FILL_NT4SYNC = "NT4SYNC"
 FILL_DRS = "DRS"
@@ -705,7 +740,7 @@ def provision(lp, setup_dir, message, paths, session_info,
               hostguid=None, adminpass=None, krbtgtpass=None, domainguid=None, 
               policyguid=None, invocationid=None, machinepass=None, 
               dnspass=None, root=None, nobody=None, nogroup=None, users=None, 
-              wheel=None, backup=None, aci=None, serverrole=None, erase=False,
+              wheel=None, backup=None, aci=None, serverrole=None,
               ldap_backend=None, ldap_backend_type=None, sitename=DEFAULTSITE):
     """Provision samba4
     
@@ -809,7 +844,7 @@ def provision(lp, setup_dir, message, paths, session_info,
         message("Setting up smb.conf")
         if serverrole == "domain controller":
             smbconfsuffix = "dc"
-        elif serverrole == "member":
+        elif serverrole == "member server":
             smbconfsuffix = "member"
         setup_file(setup_path("provision.smb.conf.%s" % smbconfsuffix), 
                    paths.smbconf, {
@@ -843,12 +878,16 @@ def provision(lp, setup_dir, message, paths, session_info,
     setup_templatesdb(paths.templates, setup_path, session_info=session_info, 
                       credentials=credentials, lp=lp)
 
+    message("Setting up idmap db")
+    setup_idmapdb(paths.idmapdb, setup_path, session_info=session_info,
+                  credentials=credentials, lp=lp)
+
     samdb = setup_samdb(paths.samdb, setup_path, session_info=session_info, 
                         credentials=credentials, lp=lp, schemadn=schemadn, 
                         configdn=configdn, domaindn=domaindn,
                         dnsdomain=dnsdomain, netbiosname=netbiosname, 
                         realm=realm, message=message, hostname=hostname, 
-                        rootdn=rootdn, erase=erase, domainsid=domainsid, 
+                        rootdn=rootdn, domainsid=domainsid, 
                         aci=aci, domainguid=domainguid, policyguid=policyguid, 
                         domainname=domain, fill=samdb_fill, 
                         adminpass=adminpass, krbtgtpass=krbtgtpass,