s4:Handle reprovision with existing partitions
[ira/wip.git] / source4 / scripting / python / samba / provision.py
index bf2e22046a927125da45ba779b06a006f1621475..49736641b6cfd75d08e4462965fb81e87daa99ad 100644 (file)
@@ -144,6 +144,11 @@ class ProvisionPaths(object):
         self.fedoradsinf = None
         self.fedoradspartitions = None
         self.fedoradssasl = None
+        self.fedoradspam = None
+        self.fedoradsrefint = None
+        self.fedoradslinkedattributes = None
+        self.fedoradsindex = None
+        self.fedoradssamba = None
         self.olmmron = None
         self.olmmrserveridsconf = None
         self.olmmrsyncreplconf = None
@@ -334,7 +339,7 @@ def setup_ldb(ldb, ldif_path, subst_vars):
     ldb.transaction_commit()
 
 
-def setup_file(template, fname, subst_vars):
+def setup_file(template, fname, subst_vars=None):
     """Setup a file in the private dir.
 
     :param template: Path of the template file.
@@ -364,6 +369,7 @@ def provision_paths_from_lp(lp, dnsdomain):
     paths.samdb = os.path.join(paths.private_dir, lp.get("sam database") or "samdb.ldb")
     paths.idmapdb = os.path.join(paths.private_dir, lp.get("idmap database") or "idmap.ldb")
     paths.secrets = os.path.join(paths.private_dir, lp.get("secrets database") or "secrets.ldb")
+    paths.privilege = os.path.join(paths.private_dir, "privilege.ldb")
     paths.dns = os.path.join(paths.private_dir, dnsdomain + ".zone")
     paths.namedconf = os.path.join(paths.private_dir, "named.conf")
     paths.namedtxt = os.path.join(paths.private_dir, "named.txt")
@@ -388,8 +394,16 @@ def provision_paths_from_lp(lp, dnsdomain):
                                             "fedorads-partitions.ldif")
     paths.fedoradssasl = os.path.join(paths.ldapdir, 
                                       "fedorads-sasl.ldif")
+    paths.fedoradspam = os.path.join(paths.ldapdir,
+                                      "fedorads-pam.ldif")
+    paths.fedoradsrefint = os.path.join(paths.ldapdir,
+                                        "fedorads-refint.ldif")
+    paths.fedoradslinkedattributes = os.path.join(paths.ldapdir,
+                                                  "fedorads-linked-attributes.ldif")
+    paths.fedoradsindex = os.path.join(paths.ldapdir,
+                                       "fedorads-index.ldif")
     paths.fedoradssamba = os.path.join(paths.ldapdir, 
-                                        "fedorads-samba.ldif")
+                                       "fedorads-samba.ldif")
     paths.olmmrserveridsconf = os.path.join(paths.ldapdir, 
                                             "mmr_serverids.conf")
     paths.olmmrsyncreplconf = os.path.join(paths.ldapdir, 
@@ -584,15 +598,25 @@ def setup_samdb_partitions(samdb_path, setup_path, message, lp, session_info,
     :note: This function always removes the local SAM LDB file. The erase 
         parameter controls whether to erase the existing data, which 
         may not be stored locally but in LDAP.
+
     """
     assert session_info is not None
 
+    old_partitions = None
+
     # We use options=["modules:"] to stop the modules loading - we
     # just want to wipe and re-initialise the database, not start it up
 
     try:
         samdb = Ldb(url=samdb_path, session_info=session_info, 
                       credentials=credentials, lp=lp, options=["modules:"])
+        res = samdb.search(base="@PARTITION", scope=SCOPE_BASE, attrs=["partition"], expression="partition=*")
+        if len(res) == 1:
+            try:
+                old_partitions = res[0]["partition"]
+            except KeyError:
+                pass
+            
         # Wipes the database
         samdb.erase_except_schema_controlled()
     except LdbError:
@@ -601,7 +625,6 @@ def setup_samdb_partitions(samdb_path, setup_path, message, lp, session_info,
                       credentials=credentials, lp=lp, options=["modules:"])
          # Wipes the database
         samdb.erase_except_schema_controlled()
-        
 
     #Add modules to the list to activate them by default
     #beware often order is important
@@ -638,20 +661,16 @@ def setup_samdb_partitions(samdb_path, setup_path, message, lp, session_info,
                     "linked_attributes",
                     "extended_dn_out_ldb"]
     modules_list2 = ["show_deleted",
+                     "new_partition",
                     "partition"]
-    domaindn_ldb = "users.ldb"
-    configdn_ldb = "configuration.ldb"
-    schemadn_ldb = "schema.ldb"
+    ldap_backend_line = "# No LDAP backend"
     if ldap_backend is not None:
-        domaindn_ldb = ldap_backend.ldapi_uri
-        configdn_ldb = ldap_backend.ldapi_uri
-        schemadn_ldb = ldap_backend.ldapi_uri
+        ldap_backend_line = "ldapBackend: %s" % ldap_backend.ldapi_uri
         
         if ldap_backend.ldap_backend_type == "fedora-ds":
             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", "extended_dn_out_dereference"]
+            tdb_modules_list = ["extended_dn_out_dereference"]
         elif ldap_backend.ldap_backend_type == "openldap":
             backend_modules = ["entryuuid", "paged_searches"]
             # OpenLDAP handles subtree renames, so we don't want to do any of these things
@@ -672,13 +691,10 @@ def setup_samdb_partitions(samdb_path, setup_path, message, lp, session_info,
     try:
         message("Setting up sam.ldb partitions and settings")
         setup_add_ldif(samdb, setup_path("provision_partitions.ldif"), {
-                "SCHEMADN": names.schemadn, 
-                "SCHEMADN_LDB": schemadn_ldb,
+                "SCHEMADN": ldb.Dn(samdb, names.schemadn).get_casefold(), 
                 "SCHEMADN_MOD2": ",objectguid",
-                "CONFIGDN": names.configdn,
-                "CONFIGDN_LDB": configdn_ldb,
-                "DOMAINDN": names.domaindn,
-                "DOMAINDN_LDB": domaindn_ldb,
+                "CONFIGDN": ldb.Dn(samdb, names.configdn).get_casefold(),
+                "DOMAINDN": ldb.Dn(samdb, names.domaindn).get_casefold(),
                 "SCHEMADN_MOD": "schema_fsmo",
                 "CONFIGDN_MOD": "naming_fsmo",
                 "DOMAINDN_MOD": "pdc_fsmo",
@@ -686,8 +702,16 @@ def setup_samdb_partitions(samdb_path, setup_path, message, lp, session_info,
                 "TDB_MODULES_LIST": tdb_modules_list_as_string,
                 "MODULES_LIST2": ",".join(modules_list2),
                 "BACKEND_MOD": ",".join(backend_modules),
+                "LDAP_BACKEND_LINE": ldap_backend_line,
         })
 
+        
+        if old_partitions is not None:
+            m = ldb.Message()
+            m.dn = ldb.Dn(samdb, "@PARTITION")
+            m["partition"] = ldb.MessageElement(old_partitions, ldb.FLAG_MOD_ADD, "partition")
+            samdb.modify(m)
+
         samdb.load_ldif_file_add(setup_path("provision_init.ldif"))
 
         message("Setting up sam.ldb rootDSE")
@@ -698,7 +722,8 @@ def setup_samdb_partitions(samdb_path, setup_path, message, lp, session_info,
         raise
 
     samdb.transaction_commit()
-    
+
+        
 def secretsdb_self_join(secretsdb, domain, 
                         netbiosname, domainsid, machinepass, 
                         realm=None, dnsdomain=None,
@@ -817,6 +842,23 @@ def setup_secretsdb(path, setup_path, session_info, credentials, lp):
 
     return secrets_ldb
 
+def setup_privileges(path, setup_path, session_info, lp):
+    """Setup the privileges database.
+
+    :param path: Path to the privileges database.
+    :param setup_path: Get the path to a setup file.
+    :param session_info: Session info.
+    :param credentials: Credentials
+    :param lp: Loadparm context
+    :return: LDB handle for the created secrets database
+    """
+    if os.path.exists(path):
+        os.unlink(path)
+    privilege_ldb = Ldb(path, session_info=session_info, lp=lp)
+    privilege_ldb.erase()
+    privilege_ldb.load_ldif_file_add(setup_path("provision_privilege.ldif"))
+
+
 def setup_registry(path, setup_path, session_info, lp):
     """Setup the registry.
     
@@ -979,12 +1021,9 @@ def setup_samdb(path, setup_path, session_info, credentials, lp,
     # And now we can connect to the DB - the schema won't be loaded from the DB
     samdb.connect(path)
 
-    # Load @OPTIONS
-    samdb.load_ldif_file_add(setup_path("provision_options.ldif"))
-
     if fill == FILL_DRS:
         return samdb
-
+        
     samdb.transaction_start()
     try:
         message("Erasing data from partitions")
@@ -1024,7 +1063,7 @@ def setup_samdb(path, setup_path, session_info, credentials, lp,
 
 
         setup_modify_ldif(samdb, setup_path("provision_basedn_modify.ldif"), {
-            "CREATTIME": str(int(time.time()) * 1e7), # seconds -> ticks
+            "CREATTIME": str(int(time.time() * 1e7)), # seconds -> ticks
             "DOMAINSID": str(domainsid),
             "SCHEMADN": names.schemadn, 
             "NETBIOSNAME": names.netbiosname,
@@ -1091,7 +1130,7 @@ def setup_samdb(path, setup_path, session_info, credentials, lp,
                 "DOMAINDN": names.domaindn})
         message("Setting up sam.ldb data")
         setup_add_ldif(samdb, setup_path("provision.ldif"), {
-            "CREATTIME": str(int(time.time()) * 1e7), # seconds -> ticks
+            "CREATTIME": str(int(time.time() * 1e7)), # seconds -> ticks
             "DOMAINDN": names.domaindn,
             "NETBIOSNAME": names.netbiosname,
             "DEFAULTSITE": names.sitename,
@@ -1288,6 +1327,9 @@ def provision(setup_dir, message, session_info,
     setup_registry(paths.hklm, setup_path, session_info, 
                    lp=lp)
 
+    message("Setting up the privileges database")
+    setup_privileges(paths.privilege, setup_path, session_info, lp=lp)
+
     message("Setting up idmap db")
     idmap = setup_idmapdb(paths.idmapdb, setup_path, session_info=session_info,
                           lp=lp)
@@ -1913,6 +1955,44 @@ def provision_fds_backend(result, paths=None, setup_path=None, names=None,
                {"SAMBADN": names.sambadn,
                 })
 
+    setup_file(setup_path("fedorads-pam.ldif"), paths.fedoradspam)
+
+    lnkattr = get_linked_attributes(names.schemadn,schema.ldb)
+
+    refint_config = data = open(setup_path("fedorads-refint-delete.ldif"), 'r').read()
+    memberof_config = ""
+    index_config = ""
+    argnum = 3
+
+    for attr in lnkattr.keys():
+        if lnkattr[attr] is not None:
+            refint_config += read_and_sub_file(setup_path("fedorads-refint-add.ldif"),
+                                                 { "ARG_NUMBER" : str(argnum) ,
+                                                   "LINK_ATTR" : attr })
+            memberof_config += read_and_sub_file(setup_path("fedorads-linked-attributes.ldif"),
+                                                 { "MEMBER_ATTR" : attr ,
+                                                   "MEMBEROF_ATTR" : lnkattr[attr] })
+            index_config += read_and_sub_file(setup_path("fedorads-index.ldif"),
+                                                 { "ATTR" : attr })
+            argnum += 1
+
+    open(paths.fedoradsrefint, 'w').write(refint_config)
+    open(paths.fedoradslinkedattributes, 'w').write(memberof_config)
+
+    attrs = ["lDAPDisplayName"]
+    res = schema.ldb.search(expression="(&(objectclass=attributeSchema)(searchFlags:1.2.840.113556.1.4.803:=1))", base=names.schemadn, scope=SCOPE_ONELEVEL, attrs=attrs)
+
+    for i in range (0, len(res)):
+        attr = res[i]["lDAPDisplayName"][0]
+
+        if attr == "objectGUID":
+            attr = "nsUniqueId"
+
+        index_config += read_and_sub_file(setup_path("fedorads-index.ldif"),
+                                             { "ATTR" : attr })
+
+    open(paths.fedoradsindex, 'w').write(index_config)
+
     setup_file(setup_path("fedorads-samba.ldif"), paths.fedoradssamba,
                 {"SAMBADN": names.sambadn, 
                  "LDAPADMINPASS": ldapadminpass