provision: fix string formatting (number of args)
[nivanova/samba-autobuild/.git] / python / samba / provision / __init__.py
index a134311d2bd5f87768448d869d446bb1b012add4..1b7762eb12b17113b8f04152c1c2d01fc2a2f452 100644 (file)
@@ -27,6 +27,8 @@
 __docformat__ = "restructuredText"
 
 from samba.compat import urllib_quote
 __docformat__ = "restructuredText"
 
 from samba.compat import urllib_quote
+from samba.compat import string_types
+from samba.compat import binary_type
 from base64 import b64encode
 import errno
 import os
 from base64 import b64encode
 import errno
 import os
@@ -38,7 +40,6 @@ import logging
 import time
 import uuid
 import socket
 import time
 import uuid
 import socket
-import string
 import tempfile
 import samba.dsdb
 
 import tempfile
 import samba.dsdb
 
@@ -46,6 +47,7 @@ import ldb
 
 from samba.auth import system_session, admin_session
 import samba
 
 from samba.auth import system_session, admin_session
 import samba
+from samba import auth
 from samba.samba3 import smbd, passdb
 from samba.samba3 import param as s3param
 from samba.dsdb import DS_DOMAIN_FUNCTION_2000
 from samba.samba3 import smbd, passdb
 from samba.samba3 import param as s3param
 from samba.dsdb import DS_DOMAIN_FUNCTION_2000
@@ -59,27 +61,26 @@ from samba import (
     valid_netbios_name,
     version,
     is_heimdal_built,
     valid_netbios_name,
     version,
     is_heimdal_built,
-    )
+)
 from samba.dcerpc import security, misc
 from samba.dcerpc.misc import (
     SEC_CHAN_BDC,
     SEC_CHAN_WKSTA,
 from samba.dcerpc import security, misc
 from samba.dcerpc.misc import (
     SEC_CHAN_BDC,
     SEC_CHAN_WKSTA,
-    )
+)
 from samba.dsdb import (
     DS_DOMAIN_FUNCTION_2003,
     DS_DOMAIN_FUNCTION_2008_R2,
     ENC_ALL_TYPES,
 from samba.dsdb import (
     DS_DOMAIN_FUNCTION_2003,
     DS_DOMAIN_FUNCTION_2008_R2,
     ENC_ALL_TYPES,
-    )
+)
 from samba.idmap import IDmapDB
 from samba.ms_display_specifiers import read_ms_ldif
 from samba.ntacls import setntacl, getntacl, dsacl2fsacl
 from samba.ndr import ndr_pack, ndr_unpack
 from samba.provision.backend import (
 from samba.idmap import IDmapDB
 from samba.ms_display_specifiers import read_ms_ldif
 from samba.ntacls import setntacl, getntacl, dsacl2fsacl
 from samba.ndr import ndr_pack, ndr_unpack
 from samba.provision.backend import (
-    ExistingBackend,
     FDSBackend,
     LDBBackend,
     OpenLDAPBackend,
     FDSBackend,
     LDBBackend,
     OpenLDAPBackend,
-    )
+)
 from samba.descriptor import (
     get_empty_descriptor,
     get_config_descriptor,
 from samba.descriptor import (
     get_empty_descriptor,
     get_config_descriptor,
@@ -101,7 +102,7 @@ from samba.descriptor import (
     get_dns_forest_microsoft_dns_descriptor,
     get_dns_domain_microsoft_dns_descriptor,
     get_managed_service_accounts_descriptor,
     get_dns_forest_microsoft_dns_descriptor,
     get_dns_domain_microsoft_dns_descriptor,
     get_managed_service_accounts_descriptor,
-    )
+)
 from samba.provision.common import (
     setup_path,
     setup_add_ldif,
 from samba.provision.common import (
     setup_path,
     setup_add_ldif,
@@ -115,7 +116,7 @@ from samba.provision.sambadns import (
     get_dnsadmins_sid,
     setup_ad_dns,
     create_dns_update_list
     get_dnsadmins_sid,
     setup_ad_dns,
     create_dns_update_list
-    )
+)
 
 import samba.param
 import samba.registry
 
 import samba.param
 import samba.registry
@@ -180,7 +181,7 @@ class ProvisionNames(object):
 
 
 def find_provision_key_parameters(samdb, secretsdb, idmapdb, paths, smbconf,
 
 
 def find_provision_key_parameters(samdb, secretsdb, idmapdb, paths, smbconf,
-        lp):
+                                  lp):
     """Get key provision parameters (realm, domain, ...) from a given provision
 
     :param samdb: An LDB object connected to the sam.ldb file
     """Get key provision parameters (realm, domain, ...) from a given provision
 
     :param samdb: An LDB object connected to the sam.ldb file
@@ -195,45 +196,45 @@ def find_provision_key_parameters(samdb, secretsdb, idmapdb, paths, smbconf,
     names.adminpass = None
 
     # NT domain, kerberos realm, root dn, domain dn, domain dns name
     names.adminpass = None
 
     # NT domain, kerberos realm, root dn, domain dn, domain dns name
-    names.domain = string.upper(lp.get("workgroup"))
+    names.domain = lp.get("workgroup").upper()
     names.realm = lp.get("realm")
     names.dnsdomain = names.realm.lower()
     basedn = samba.dn_from_dns_name(names.dnsdomain)
     names.realm = lp.get("realm")
     names.dnsdomain = names.realm.lower()
     basedn = samba.dn_from_dns_name(names.dnsdomain)
-    names.realm = string.upper(names.realm)
+    names.realm = names.realm.upper()
     # netbiosname
     # Get the netbiosname first (could be obtained from smb.conf in theory)
     res = secretsdb.search(expression="(flatname=%s)" %
     # netbiosname
     # Get the netbiosname first (could be obtained from smb.conf in theory)
     res = secretsdb.search(expression="(flatname=%s)" %
-                            names.domain,base="CN=Primary Domains",
-                            scope=ldb.SCOPE_SUBTREE, attrs=["sAMAccountName"])
-    names.netbiosname = str(res[0]["sAMAccountName"]).replace("$","")
+                           names.domain, base="CN=Primary Domains",
+                           scope=ldb.SCOPE_SUBTREE, attrs=["sAMAccountName"])
+    names.netbiosname = str(res[0]["sAMAccountName"]).replace("$", "")
 
     names.smbconf = smbconf
 
     # That's a bit simplistic but it's ok as long as we have only 3
     # partitions
     current = samdb.search(expression="(objectClass=*)",
 
     names.smbconf = smbconf
 
     # That's a bit simplistic but it's ok as long as we have only 3
     # partitions
     current = samdb.search(expression="(objectClass=*)",
-        base="", scope=ldb.SCOPE_BASE,
-        attrs=["defaultNamingContext", "schemaNamingContext",
-               "configurationNamingContext","rootDomainNamingContext",
-               "namingContexts"])
+                           base="", scope=ldb.SCOPE_BASE,
+                           attrs=["defaultNamingContext", "schemaNamingContext",
+                                  "configurationNamingContext", "rootDomainNamingContext",
+                                  "namingContexts"])
 
 
-    names.configdn = current[0]["configurationNamingContext"][0]
-    names.schemadn = current[0]["schemaNamingContext"][0]
+    names.configdn = str(current[0]["configurationNamingContext"][0])
+    names.schemadn = str(current[0]["schemaNamingContext"][0])
     if not (ldb.Dn(samdb, basedn) == (ldb.Dn(samdb,
     if not (ldb.Dn(samdb, basedn) == (ldb.Dn(samdb,
-                                       current[0]["defaultNamingContext"][0].decode('utf8')))):
+                                             current[0]["defaultNamingContext"][0].decode('utf8')))):
         raise ProvisioningError(("basedn in %s (%s) and from %s (%s)"
                                  "is not the same ..." % (paths.samdb,
         raise ProvisioningError(("basedn in %s (%s) and from %s (%s)"
                                  "is not the same ..." % (paths.samdb,
-                                    str(current[0]["defaultNamingContext"][0].decode('utf8')),
-                                    paths.smbconf, basedn)))
+                                                          str(current[0]["defaultNamingContext"][0].decode('utf8')),
+                                                          paths.smbconf, basedn)))
 
 
-    names.domaindn=current[0]["defaultNamingContext"][0]
-    names.rootdn=current[0]["rootDomainNamingContext"][0]
-    names.ncs=current[0]["namingContexts"]
+    names.domaindn = str(current[0]["defaultNamingContext"][0])
+    names.rootdn = str(current[0]["rootDomainNamingContext"][0])
+    names.ncs = current[0]["namingContexts"]
     names.dnsforestdn = None
     names.dnsdomaindn = None
 
     for i in range(0, len(names.ncs)):
     names.dnsforestdn = None
     names.dnsdomaindn = None
 
     for i in range(0, len(names.ncs)):
-        nc = names.ncs[i]
+        nc = str(names.ncs[i])
 
         dnsforestdn = "DC=ForestDnsZones,%s" % (str(names.rootdn))
         if nc == dnsforestdn:
 
         dnsforestdn = "DC=ForestDnsZones,%s" % (str(names.rootdn))
         if nc == dnsforestdn:
@@ -247,7 +248,7 @@ def find_provision_key_parameters(samdb, secretsdb, idmapdb, paths, smbconf,
 
     # default site name
     res3 = samdb.search(expression="(objectClass=site)",
 
     # default site name
     res3 = samdb.search(expression="(objectClass=site)",
-        base="CN=Sites," + names.configdn, scope=ldb.SCOPE_ONELEVEL, attrs=["cn"])
+                        base="CN=Sites," + str(names.configdn), scope=ldb.SCOPE_ONELEVEL, attrs=["cn"])
     names.sitename = str(res3[0]["cn"])
 
     # dns hostname and server dn
     names.sitename = str(res3[0]["cn"])
 
     # dns hostname and server dn
@@ -260,26 +261,26 @@ def find_provision_key_parameters(samdb, secretsdb, idmapdb, paths, smbconf,
     names.hostname = str(res4[0]["dNSHostName"]).replace("." + names.dnsdomain, "")
 
     server_res = samdb.search(expression="serverReference=%s" % res4[0].dn,
     names.hostname = str(res4[0]["dNSHostName"]).replace("." + names.dnsdomain, "")
 
     server_res = samdb.search(expression="serverReference=%s" % res4[0].dn,
-                                attrs=[], base=names.configdn)
+                              attrs=[], base=names.configdn)
     names.serverdn = str(server_res[0].dn)
 
     # invocation id/objectguid
     res5 = samdb.search(expression="(objectClass=*)",
     names.serverdn = str(server_res[0].dn)
 
     # invocation id/objectguid
     res5 = samdb.search(expression="(objectClass=*)",
-            base="CN=NTDS Settings,%s" % str(names.serverdn),
-            scope=ldb.SCOPE_BASE,
-            attrs=["invocationID", "objectGUID"])
+                        base="CN=NTDS Settings,%s" % str(names.serverdn),
+                        scope=ldb.SCOPE_BASE,
+                        attrs=["invocationID", "objectGUID"])
     names.invocation = str(ndr_unpack(misc.GUID, res5[0]["invocationId"][0]))
     names.ntdsguid = str(ndr_unpack(misc.GUID, res5[0]["objectGUID"][0]))
 
     # domain guid/sid
     res6 = samdb.search(expression="(objectClass=*)", base=basedn,
     names.invocation = str(ndr_unpack(misc.GUID, res5[0]["invocationId"][0]))
     names.ntdsguid = str(ndr_unpack(misc.GUID, res5[0]["objectGUID"][0]))
 
     # domain guid/sid
     res6 = samdb.search(expression="(objectClass=*)", base=basedn,
-            scope=ldb.SCOPE_BASE, attrs=["objectGUID",
-                "objectSid","msDS-Behavior-Version" ])
+                        scope=ldb.SCOPE_BASE, attrs=["objectGUID",
+                                                     "objectSid", "msDS-Behavior-Version"])
     names.domainguid = str(ndr_unpack(misc.GUID, res6[0]["objectGUID"][0]))
     names.domainguid = str(ndr_unpack(misc.GUID, res6[0]["objectGUID"][0]))
-    names.domainsid = ndr_unpack( security.dom_sid, res6[0]["objectSid"][0])
-    names.forestsid = ndr_unpack( security.dom_sid, res6[0]["objectSid"][0])
+    names.domainsid = ndr_unpack(security.dom_sid, res6[0]["objectSid"][0])
+    names.forestsid = ndr_unpack(security.dom_sid, res6[0]["objectSid"][0])
     if res6[0].get("msDS-Behavior-Version") is None or \
     if res6[0].get("msDS-Behavior-Version") is None or \
-        int(res6[0]["msDS-Behavior-Version"][0]) < DS_DOMAIN_FUNCTION_2000:
+            int(res6[0]["msDS-Behavior-Version"][0]) < DS_DOMAIN_FUNCTION_2000:
         names.domainlevel = DS_DOMAIN_FUNCTION_2000
     else:
         names.domainlevel = int(res6[0]["msDS-Behavior-Version"][0])
         names.domainlevel = DS_DOMAIN_FUNCTION_2000
     else:
         names.domainlevel = int(res6[0]["msDS-Behavior-Version"][0])
@@ -287,15 +288,15 @@ def find_provision_key_parameters(samdb, secretsdb, idmapdb, paths, smbconf,
     # policy guid
     res7 = samdb.search(expression="(name={%s})" % DEFAULT_POLICY_GUID,
                         base="CN=Policies,CN=System," + basedn,
     # policy guid
     res7 = samdb.search(expression="(name={%s})" % DEFAULT_POLICY_GUID,
                         base="CN=Policies,CN=System," + basedn,
-                        scope=ldb.SCOPE_ONELEVEL, attrs=["cn","displayName"])
-    names.policyid = str(res7[0]["cn"]).replace("{","").replace("}","")
+                        scope=ldb.SCOPE_ONELEVEL, attrs=["cn", "displayName"])
+    names.policyid = str(res7[0]["cn"]).replace("{", "").replace("}", "")
     # dc policy guid
     res8 = samdb.search(expression="(name={%s})" % DEFAULT_DC_POLICY_GUID,
                         base="CN=Policies,CN=System," + basedn,
                         scope=ldb.SCOPE_ONELEVEL,
     # dc policy guid
     res8 = samdb.search(expression="(name={%s})" % DEFAULT_DC_POLICY_GUID,
                         base="CN=Policies,CN=System," + basedn,
                         scope=ldb.SCOPE_ONELEVEL,
-                        attrs=["cn","displayName"])
+                        attrs=["cn", "displayName"])
     if len(res8) == 1:
     if len(res8) == 1:
-        names.policyid_dc = str(res8[0]["cn"]).replace("{","").replace("}","")
+        names.policyid_dc = str(res8[0]["cn"]).replace("{", "").replace("}", "")
     else:
         names.policyid_dc = None
 
     else:
         names.policyid_dc = None
 
@@ -304,8 +305,8 @@ def find_provision_key_parameters(samdb, secretsdb, idmapdb, paths, smbconf,
                           attrs=["xidNumber", "type"])
     if len(res9) != 1:
         raise ProvisioningError("Unable to find uid/gid for Domain Admins rid (%s-%s" % (str(names.domainsid), security.DOMAIN_RID_ADMINISTRATOR))
                           attrs=["xidNumber", "type"])
     if len(res9) != 1:
         raise ProvisioningError("Unable to find uid/gid for Domain Admins rid (%s-%s" % (str(names.domainsid), security.DOMAIN_RID_ADMINISTRATOR))
-    if res9[0]["type"][0] == "ID_TYPE_BOTH":
-        names.root_gid = res9[0]["xidNumber"][0]
+    if str(res9[0]["type"][0]) == "ID_TYPE_BOTH":
+        names.root_gid = int(res9[0]["xidNumber"][0])
     else:
         names.root_gid = pwd.getpwuid(int(res9[0]["xidNumber"][0])).pw_gid
 
     else:
         names.root_gid = pwd.getpwuid(int(res9[0]["xidNumber"][0])).pw_gid
 
@@ -363,15 +364,17 @@ def update_provision_usn(samdb, low, high, id, replace=False):
                              scope=ldb.SCOPE_BASE,
                              attrs=[LAST_PROVISION_USN_ATTRIBUTE, "dn"])
         for e in entry[0][LAST_PROVISION_USN_ATTRIBUTE]:
                              scope=ldb.SCOPE_BASE,
                              attrs=[LAST_PROVISION_USN_ATTRIBUTE, "dn"])
         for e in entry[0][LAST_PROVISION_USN_ATTRIBUTE]:
-            if not re.search(';', e):
-                e = "%s;%s" % (e, id)
+            if not re.search(';', str(e)):
+                e = "%s;%s" % (str(e), id)
             tab.append(str(e))
 
     tab.append("%s-%s;%s" % (low, high, id))
     delta = ldb.Message()
     delta.dn = ldb.Dn(samdb, "@PROVISION")
             tab.append(str(e))
 
     tab.append("%s-%s;%s" % (low, high, id))
     delta = ldb.Message()
     delta.dn = ldb.Dn(samdb, "@PROVISION")
-    delta[LAST_PROVISION_USN_ATTRIBUTE] = ldb.MessageElement(tab,
-        ldb.FLAG_MOD_REPLACE, LAST_PROVISION_USN_ATTRIBUTE)
+    delta[LAST_PROVISION_USN_ATTRIBUTE] = \
+        ldb.MessageElement(tab,
+                           ldb.FLAG_MOD_REPLACE,
+                           LAST_PROVISION_USN_ATTRIBUTE)
     entry = samdb.search(expression='provisionnerID=*',
                          base="@PROVISION", scope=ldb.SCOPE_BASE,
                          attrs=["provisionnerID"])
     entry = samdb.search(expression='provisionnerID=*',
                          base="@PROVISION", scope=ldb.SCOPE_BASE,
                          attrs=["provisionnerID"])
@@ -397,12 +400,14 @@ def set_provision_usn(samdb, low, high, id):
 
     delta = ldb.Message()
     delta.dn = ldb.Dn(samdb, "@PROVISION")
 
     delta = ldb.Message()
     delta.dn = ldb.Dn(samdb, "@PROVISION")
-    delta[LAST_PROVISION_USN_ATTRIBUTE] = ldb.MessageElement(tab,
-        ldb.FLAG_MOD_ADD, LAST_PROVISION_USN_ATTRIBUTE)
+    delta[LAST_PROVISION_USN_ATTRIBUTE] = \
+        ldb.MessageElement(tab,
+                           ldb.FLAG_MOD_ADD,
+                           LAST_PROVISION_USN_ATTRIBUTE)
     samdb.add(delta)
 
 
     samdb.add(delta)
 
 
-def get_max_usn(samdb,basedn):
+def get_max_usn(samdb, basedn):
     """ This function return the biggest USN present in the provision
 
     :param samdb: A LDB object pointing to the sam.ldb
     """ This function return the biggest USN present in the provision
 
     :param samdb: A LDB object pointing to the sam.ldb
@@ -410,11 +415,11 @@ def get_max_usn(samdb,basedn):
                     (ie. DC=foo, DC=bar)
     :return: The biggest USN in the provision"""
 
                     (ie. DC=foo, DC=bar)
     :return: The biggest USN in the provision"""
 
-    res = samdb.search(expression="objectClass=*",base=basedn,
-                         scope=ldb.SCOPE_SUBTREE,attrs=["uSNChanged"],
-                         controls=["search_options:1:2",
-                                   "server_sort:1:1:uSNChanged",
-                                   "paged_results:1:1"])
+    res = samdb.search(expression="objectClass=*", base=basedn,
+                       scope=ldb.SCOPE_SUBTREE, attrs=["uSNChanged"],
+                       controls=["search_options:1:2",
+                                 "server_sort:1:1:uSNChanged",
+                                 "paged_results:1:1"])
     return res[0]["uSNChanged"]
 
 
     return res[0]["uSNChanged"]
 
 
@@ -427,8 +432,8 @@ def get_last_provision_usn(sam):
     """
     try:
         entry = sam.search(expression="%s=*" % LAST_PROVISION_USN_ATTRIBUTE,
     """
     try:
         entry = sam.search(expression="%s=*" % LAST_PROVISION_USN_ATTRIBUTE,
-                       base="@PROVISION", scope=ldb.SCOPE_BASE,
-                       attrs=[LAST_PROVISION_USN_ATTRIBUTE, "provisionnerID"])
+                           base="@PROVISION", scope=ldb.SCOPE_BASE,
+                           attrs=[LAST_PROVISION_USN_ATTRIBUTE, "provisionnerID"])
     except ldb.LdbError as e1:
         (ecode, emsg) = e1.args
         if ecode == ldb.ERR_NO_SUCH_OBJECT:
     except ldb.LdbError as e1:
         (ecode, emsg) = e1.args
         if ecode == ldb.ERR_NO_SUCH_OBJECT:
@@ -507,7 +512,7 @@ def check_install(lp, session_info, credentials):
     if lp.get("realm") == "":
         raise Exception("Realm empty")
     samdb = Ldb(lp.samdb_url(), session_info=session_info,
     if lp.get("realm") == "":
         raise Exception("Realm empty")
     samdb = Ldb(lp.samdb_url(), session_info=session_info,
-            credentials=credentials, lp=lp)
+                credentials=credentials, lp=lp)
     if len(samdb.search("(cn=Administrator)")) != 1:
         raise ProvisioningError("No administrator account found")
 
     if len(samdb.search("(cn=Administrator)")) != 1:
         raise ProvisioningError("No administrator account found")
 
@@ -527,8 +532,12 @@ def findnss(nssfn, names):
     raise KeyError("Unable to find user/group in %r" % names)
 
 
     raise KeyError("Unable to find user/group in %r" % names)
 
 
-findnss_uid = lambda names: findnss(pwd.getpwnam, names)[2]
-findnss_gid = lambda names: findnss(grp.getgrnam, names)[2]
+def findnss_uid(names):
+    return findnss(pwd.getpwnam, names)[2]
+
+
+def findnss_gid(names):
+    return findnss(grp.getgrnam, names)[2]
 
 
 def provision_paths_from_lp(lp, dnsdomain):
 
 
 def provision_paths_from_lp(lp, dnsdomain):
@@ -605,7 +614,9 @@ def guess_names(lp=None, hostname=None, domain=None, dnsdomain=None,
     if dnsdomain is None:
         dnsdomain = lp.get("realm")
         if dnsdomain is None or dnsdomain == "":
     if dnsdomain is None:
         dnsdomain = lp.get("realm")
         if dnsdomain is None or dnsdomain == "":
-            raise ProvisioningError("guess_names: 'realm' not specified in supplied %s!", lp.configfile)
+            raise ProvisioningError(
+                "guess_names: 'realm' not specified in supplied %s!" %
+                lp.configfile)
 
     dnsdomain = dnsdomain.lower()
 
 
     dnsdomain = dnsdomain.lower()
 
@@ -673,7 +684,7 @@ def guess_names(lp=None, hostname=None, domain=None, dnsdomain=None,
         dnsdomain = netbiosname.lower()
 
     if rootdn is None:
         dnsdomain = netbiosname.lower()
 
     if rootdn is None:
-       rootdn = domaindn
+        rootdn = domaindn
 
     if configdn is None:
         configdn = "CN=Configuration," + rootdn
 
     if configdn is None:
         configdn = "CN=Configuration," + rootdn
@@ -700,6 +711,7 @@ def guess_names(lp=None, hostname=None, domain=None, dnsdomain=None,
 
     return names
 
 
     return names
 
+
 def make_smbconf(smbconf, hostname, domain, realm, targetdir,
                  serverrole=None, eadb=False, use_ntvfs=False, lp=None,
                  global_param=None):
 def make_smbconf(smbconf, hostname, domain, realm, targetdir,
                  serverrole=None, eadb=False, use_ntvfs=False, lp=None,
                  global_param=None):
@@ -726,11 +738,11 @@ def make_smbconf(smbconf, hostname, domain, realm, targetdir,
         "workgroup": domain,
         "realm": realm,
         "server role": serverrole,
         "workgroup": domain,
         "realm": realm,
         "server role": serverrole,
-        }
+    }
 
     if lp is None:
         lp = samba.param.LoadParm()
 
     if lp is None:
         lp = samba.param.LoadParm()
-    #Load non-existent file
+    # Load non-existent file
     if os.path.exists(smbconf):
         lp.load(smbconf)
 
     if os.path.exists(smbconf):
         lp.load(smbconf)
 
@@ -744,10 +756,12 @@ def make_smbconf(smbconf, hostname, domain, realm, targetdir,
         global_settings["lock dir"] = os.path.abspath(targetdir)
         global_settings["state directory"] = os.path.abspath(os.path.join(targetdir, "state"))
         global_settings["cache directory"] = os.path.abspath(os.path.join(targetdir, "cache"))
         global_settings["lock dir"] = os.path.abspath(targetdir)
         global_settings["state directory"] = os.path.abspath(os.path.join(targetdir, "state"))
         global_settings["cache directory"] = os.path.abspath(os.path.join(targetdir, "cache"))
+        global_settings["binddns dir"] = os.path.abspath(os.path.join(targetdir, "bind-dns"))
 
         lp.set("lock dir", os.path.abspath(targetdir))
 
         lp.set("lock dir", os.path.abspath(targetdir))
-        lp.set("state directory",  global_settings["state directory"])
+        lp.set("state directory", global_settings["state directory"])
         lp.set("cache directory", global_settings["cache directory"])
         lp.set("cache directory", global_settings["cache directory"])
+        lp.set("binddns dir", global_settings["binddns dir"])
 
     if eadb:
         if use_ntvfs and not lp.get("posix:eadb"):
 
     if eadb:
         if use_ntvfs and not lp.get("posix:eadb"):
@@ -767,7 +781,7 @@ def make_smbconf(smbconf, hostname, domain, realm, targetdir,
     if serverrole == "active directory domain controller":
         shares["sysvol"] = os.path.join(lp.get("state directory"), "sysvol")
         shares["netlogon"] = os.path.join(shares["sysvol"], realm.lower(),
     if serverrole == "active directory domain controller":
         shares["sysvol"] = os.path.join(lp.get("state directory"), "sysvol")
         shares["netlogon"] = os.path.join(shares["sysvol"], realm.lower(),
-            "scripts")
+                                          "scripts")
     else:
         global_settings["passdb backend"] = "samba_dsdb"
 
     else:
         global_settings["passdb backend"] = "samba_dsdb"
 
@@ -871,7 +885,6 @@ def setup_samdb_partitions(samdb_path, logger, lp, session_info,
                 "BACKEND_STORE": backend_store_line
         })
 
                 "BACKEND_STORE": backend_store_line
         })
 
-
         setup_add_ldif(samdb, setup_path("provision_init.ldif"), {
                 "BACKEND_TYPE": provision_backend.type,
                 "SERVER_ROLE": serverrole,
         setup_add_ldif(samdb, setup_path("provision_init.ldif"), {
                 "BACKEND_TYPE": provision_backend.type,
                 "SERVER_ROLE": serverrole,
@@ -899,11 +912,11 @@ def secretsdb_self_join(secretsdb, domain,
     :param machinepass: Machine password
     """
     attrs = ["whenChanged",
     :param machinepass: Machine password
     """
     attrs = ["whenChanged",
-           "secret",
-           "priorSecret",
-           "priorChanged",
-           "krb5Keytab",
-           "privateKeytab"]
+             "secret",
+             "priorSecret",
+             "priorChanged",
+             "krb5Keytab",
+             "privateKeytab"]
 
     if realm is not None:
         if dnsdomain is None:
 
     if realm is not None:
         if dnsdomain is None:
@@ -936,8 +949,8 @@ def secretsdb_self_join(secretsdb, domain,
     # but we don't delete the old record that we are about to modify,
     # because that would delete the keytab and previous password.
     res = secretsdb.search(base="cn=Primary Domains", attrs=attrs,
     # but we don't delete the old record that we are about to modify,
     # because that would delete the keytab and previous password.
     res = secretsdb.search(base="cn=Primary Domains", attrs=attrs,
-        expression=("(&(|(flatname=%s)(realm=%s)(objectSid=%s))(objectclass=primaryDomain)(!(distinguishedName=%s)))" % (domain, realm, str(domainsid), str(msg.dn))),
-        scope=ldb.SCOPE_ONELEVEL)
+                           expression=("(&(|(flatname=%s)(realm=%s)(objectSid=%s))(objectclass=primaryDomain)(!(distinguishedName=%s)))" % (domain, realm, str(domainsid), str(msg.dn))),
+                           scope=ldb.SCOPE_ONELEVEL)
 
     for del_msg in res:
         secretsdb.delete(del_msg.dn)
 
     for del_msg in res:
         secretsdb.delete(del_msg.dn)
@@ -967,11 +980,11 @@ def secretsdb_self_join(secretsdb, domain,
         secretsdb.modify(msg)
         secretsdb.rename(res[0].dn, msg.dn)
     else:
         secretsdb.modify(msg)
         secretsdb.rename(res[0].dn, msg.dn)
     else:
-        spn = [ 'HOST/%s' % shortname ]
+        spn = ['HOST/%s' % shortname]
         if secure_channel_type == SEC_CHAN_BDC and dnsname is not None:
             # we are a domain controller then we add servicePrincipalName
             # entries for the keytab code to update.
         if secure_channel_type == SEC_CHAN_BDC and dnsname is not None:
             # we are a domain controller then we add servicePrincipalName
             # entries for the keytab code to update.
-            spn.extend([ 'HOST/%s' % dnsname ])
+            spn.extend(['HOST/%s' % dnsname])
         msg["servicePrincipalName"] = spn
 
         secretsdb.add(msg)
         msg["servicePrincipalName"] = spn
 
         secretsdb.add(msg)
@@ -1018,17 +1031,17 @@ def setup_secretsdb(paths, session_info, backend_credentials, lp):
             backend_credentials.authentication_requested()):
             if backend_credentials.get_bind_dn() is not None:
                 setup_add_ldif(secrets_ldb,
             backend_credentials.authentication_requested()):
             if backend_credentials.get_bind_dn() is not None:
                 setup_add_ldif(secrets_ldb,
-                    setup_path("secrets_simple_ldap.ldif"), {
-                        "LDAPMANAGERDN": backend_credentials.get_bind_dn(),
-                        "LDAPMANAGERPASS_B64": b64encode(backend_credentials.get_password())
-                        })
+                               setup_path("secrets_simple_ldap.ldif"), {
+                                   "LDAPMANAGERDN": backend_credentials.get_bind_dn(),
+                                   "LDAPMANAGERPASS_B64": b64encode(backend_credentials.get_password()).decode('utf8')
+                               })
             else:
                 setup_add_ldif(secrets_ldb,
             else:
                 setup_add_ldif(secrets_ldb,
-                    setup_path("secrets_sasl_ldap.ldif"), {
-                        "LDAPADMINUSER": backend_credentials.get_username(),
-                        "LDAPADMINREALM": backend_credentials.get_realm(),
-                        "LDAPADMINPASS_B64": b64encode(backend_credentials.get_password())
-                        })
+                               setup_path("secrets_sasl_ldap.ldif"), {
+                                   "LDAPADMINUSER": backend_credentials.get_username(),
+                                   "LDAPADMINREALM": backend_credentials.get_realm(),
+                                   "LDAPADMINPASS_B64": b64encode(backend_credentials.get_password()).decode('utf8')
+                               })
     except:
         secrets_ldb.transaction_cancel()
         raise
     except:
         secrets_ldb.transaction_cancel()
         raise
@@ -1050,6 +1063,7 @@ def setup_privileges(path, session_info, lp):
     privilege_ldb.erase()
     privilege_ldb.load_ldif_file_add(setup_path("provision_privilege.ldif"))
 
     privilege_ldb.erase()
     privilege_ldb.load_ldif_file_add(setup_path("provision_privilege.ldif"))
 
+
 def setup_encrypted_secrets_key(path):
     """Setup the encrypted secrets key file.
 
 def setup_encrypted_secrets_key(path):
     """Setup the encrypted secrets key file.
 
@@ -1070,7 +1084,7 @@ def setup_encrypted_secrets_key(path):
     finally:
         os.umask(umask_original)
 
     finally:
         os.umask(umask_original)
 
-    with os.fdopen(fd, 'w') as f:
+    with os.fdopen(fd, 'wb') as f:
         key = samba.generate_random_bytes(16)
         f.write(key)
 
         key = samba.generate_random_bytes(16)
         f.write(key)
 
@@ -1116,20 +1130,20 @@ def setup_samdb_rootdse(samdb, names):
     setup_add_ldif(samdb, setup_path("provision_rootdse_add.ldif"), {
         "SCHEMADN": names.schemadn,
         "DOMAINDN": names.domaindn,
     setup_add_ldif(samdb, setup_path("provision_rootdse_add.ldif"), {
         "SCHEMADN": names.schemadn,
         "DOMAINDN": names.domaindn,
-        "ROOTDN"  : names.rootdn,
+        "ROOTDN": names.rootdn,
         "CONFIGDN": names.configdn,
         "SERVERDN": names.serverdn,
         "CONFIGDN": names.configdn,
         "SERVERDN": names.serverdn,
-        })
+    })
 
 
 def setup_self_join(samdb, admin_session_info, names, fill, machinepass,
 
 
 def setup_self_join(samdb, admin_session_info, names, fill, machinepass,
-        dns_backend, dnspass, domainsid, next_rid, invocationid,
-        policyguid, policyguid_dc,
-        domainControllerFunctionality, ntdsguid=None, dc_rid=None):
+                    dns_backend, dnspass, domainsid, next_rid, invocationid,
+                    policyguid, policyguid_dc,
+                    domainControllerFunctionality, ntdsguid=None, dc_rid=None):
     """Join a host to its own domain."""
     assert isinstance(invocationid, str)
     if ntdsguid is not None:
     """Join a host to its own domain."""
     assert isinstance(invocationid, str)
     if ntdsguid is not None:
-        ntdsguid_line = "objectGUID: %s\n"%ntdsguid
+        ntdsguid_line = "objectGUID: %s\n" % ntdsguid
     else:
         ntdsguid_line = ""
 
     else:
         ntdsguid_line = ""
 
@@ -1144,7 +1158,7 @@ def setup_self_join(samdb, admin_session_info, names, fill, machinepass,
               "INVOCATIONID": invocationid,
               "NETBIOSNAME": names.netbiosname,
               "DNSNAME": "%s.%s" % (names.hostname, names.dnsdomain),
               "INVOCATIONID": invocationid,
               "NETBIOSNAME": names.netbiosname,
               "DNSNAME": "%s.%s" % (names.hostname, names.dnsdomain),
-              "MACHINEPASS_B64": b64encode(machinepass.encode('utf-16-le')),
+              "MACHINEPASS_B64": b64encode(machinepass.encode('utf-16-le')).decode('utf8'),
               "DOMAINSID": str(domainsid),
               "DCRID": str(dc_rid),
               "SAMBA_VERSION_STRING": version,
               "DOMAINSID": str(domainsid),
               "DCRID": str(dc_rid),
               "SAMBA_VERSION_STRING": version,
@@ -1171,7 +1185,7 @@ def setup_self_join(samdb, admin_session_info, names, fill, machinepass,
                 "INVOCATIONID": invocationid,
                 "NETBIOSNAME": names.netbiosname,
                 "DNSNAME": "%s.%s" % (names.hostname, names.dnsdomain),
                 "INVOCATIONID": invocationid,
                 "NETBIOSNAME": names.netbiosname,
                 "DNSNAME": "%s.%s" % (names.hostname, names.dnsdomain),
-                "MACHINEPASS_B64": b64encode(machinepass.encode('utf-16-le')),
+                "MACHINEPASS_B64": b64encode(machinepass.encode('utf-16-le')).decode('utf8'),
                 "DOMAINSID": str(domainsid),
                 "DCRID": str(dc_rid),
                 "SAMBA_VERSION_STRING": version,
                 "DOMAINSID": str(domainsid),
                 "DCRID": str(dc_rid),
                 "SAMBA_VERSION_STRING": version,
@@ -1181,13 +1195,13 @@ def setup_self_join(samdb, admin_session_info, names, fill, machinepass,
 
     # Setup fSMORoleOwner entries to point at the newly created DC entry
         setup_modify_ldif(samdb,
 
     # Setup fSMORoleOwner entries to point at the newly created DC entry
         setup_modify_ldif(samdb,
-            setup_path("provision_self_join_modify_config.ldif"), {
-                "CONFIGDN": names.configdn,
-                "SCHEMADN": names.schemadn,
-                "DEFAULTSITE": names.sitename,
-                "NETBIOSNAME": names.netbiosname,
-                "SERVERDN": names.serverdn,
-                })
+                          setup_path("provision_self_join_modify_config.ldif"), {
+                              "CONFIGDN": names.configdn,
+                              "SCHEMADN": names.schemadn,
+                              "DEFAULTSITE": names.sitename,
+                              "NETBIOSNAME": names.netbiosname,
+                              "SERVERDN": names.serverdn,
+                          })
 
     system_session_info = system_session()
     samdb.set_session_info(system_session_info)
 
     system_session_info = system_session()
     samdb.set_session_info(system_session_info)
@@ -1208,9 +1222,9 @@ def setup_self_join(samdb, admin_session_info, names, fill, machinepass,
         setup_add_ldif(samdb, setup_path("provision_dns_add_samba.ldif"), {
               "DNSDOMAIN": names.dnsdomain,
               "DOMAINDN": names.domaindn,
         setup_add_ldif(samdb, setup_path("provision_dns_add_samba.ldif"), {
               "DNSDOMAIN": names.dnsdomain,
               "DOMAINDN": names.domaindn,
-              "DNSPASS_B64": b64encode(dnspass.encode('utf-16-le')),
-              "HOSTNAME" : names.hostname,
-              "DNSNAME" : '%s.%s' % (
+              "DNSPASS_B64": b64encode(dnspass.encode('utf-16-le')).decode('utf8'),
+              "HOSTNAME": names.hostname,
+              "DNSNAME": '%s.%s' % (
                   names.netbiosname.lower(), names.dnsdomain.lower())
               })
 
                   names.netbiosname.lower(), names.dnsdomain.lower())
               })
 
@@ -1253,16 +1267,16 @@ def create_default_gpo(sysvolpath, dnsdomain, policyguid, policyguid_dc):
     :param policyguid: GUID of the default domain policy
     :param policyguid_dc: GUID of the default domain controler policy
     """
     :param policyguid: GUID of the default domain policy
     :param policyguid_dc: GUID of the default domain controler policy
     """
-    policy_path = getpolicypath(sysvolpath,dnsdomain,policyguid)
+    policy_path = getpolicypath(sysvolpath, dnsdomain, policyguid)
     create_gpo_struct(policy_path)
 
     create_gpo_struct(policy_path)
 
-    policy_path = getpolicypath(sysvolpath,dnsdomain,policyguid_dc)
+    policy_path = getpolicypath(sysvolpath, dnsdomain, policyguid_dc)
     create_gpo_struct(policy_path)
 
 
 def setup_samdb(path, session_info, provision_backend, lp, names,
     create_gpo_struct(policy_path)
 
 
 def setup_samdb(path, session_info, provision_backend, lp, names,
-        logger, fill, serverrole, schema, am_rodc=False,
-        plaintext_secrets=False, backend_store=None):
+                logger, fill, serverrole, schema, am_rodc=False,
+                plaintext_secrets=False, backend_store=None):
     """Setup a complete SAM Database.
 
     :note: This will wipe the main SAM database file!
     """Setup a complete SAM Database.
 
     :note: This will wipe the main SAM database file!
@@ -1270,9 +1284,9 @@ def setup_samdb(path, session_info, provision_backend, lp, names,
 
     # Also wipes the database
     setup_samdb_partitions(path, logger=logger, lp=lp,
 
     # Also wipes the database
     setup_samdb_partitions(path, logger=logger, lp=lp,
-        provision_backend=provision_backend, session_info=session_info,
-        names=names, serverrole=serverrole, plaintext_secrets=plaintext_secrets,
-        backend_store=backend_store)
+                           provision_backend=provision_backend, session_info=session_info,
+                           names=names, serverrole=serverrole, plaintext_secrets=plaintext_secrets,
+                           backend_store=backend_store)
 
     # Load the database, but don's load the global schema and don't connect
     # quite yet
 
     # Load the database, but don's load the global schema and don't connect
     # quite yet
@@ -1309,10 +1323,10 @@ def setup_samdb(path, session_info, provision_backend, lp, names,
 
 
 def fill_samdb(samdb, lp, names, logger, policyguid,
 
 
 def fill_samdb(samdb, lp, names, logger, policyguid,
-        policyguid_dc, fill, adminpass, krbtgtpass, machinepass, dns_backend,
-        dnspass, invocationid, ntdsguid, serverrole, am_rodc=False,
-        dom_for_fun_level=None, schema=None, next_rid=None, dc_rid=None,
-        backend_store=None):
+               policyguid_dc, fill, adminpass, krbtgtpass, machinepass, dns_backend,
+               dnspass, invocationid, ntdsguid, serverrole, am_rodc=False,
+               dom_for_fun_level=None, schema=None, next_rid=None, dc_rid=None,
+               backend_store=None):
 
     if next_rid is None:
         next_rid = 1000
 
     if next_rid is None:
         next_rid = 1000
@@ -1352,7 +1366,7 @@ def fill_samdb(samdb, lp, names, logger, policyguid,
     samdb.set_opaque_integer("domainFunctionality", domainFunctionality)
     samdb.set_opaque_integer("forestFunctionality", forestFunctionality)
     samdb.set_opaque_integer("domainControllerFunctionality",
     samdb.set_opaque_integer("domainFunctionality", domainFunctionality)
     samdb.set_opaque_integer("forestFunctionality", forestFunctionality)
     samdb.set_opaque_integer("domainControllerFunctionality",
-        domainControllerFunctionality)
+                             domainControllerFunctionality)
 
     samdb.set_domain_sid(str(names.domainsid))
     samdb.set_invocation_id(invocationid)
 
     samdb.set_domain_sid(str(names.domainsid))
     samdb.set_invocation_id(invocationid)
@@ -1367,7 +1381,7 @@ def fill_samdb(samdb, lp, names, logger, policyguid,
     else:
         domainguid_line = ""
 
     else:
         domainguid_line = ""
 
-    descr = b64encode(get_domain_descriptor(names.domainsid))
+    descr = b64encode(get_domain_descriptor(names.domainsid)).decode('utf8')
     setup_add_ldif(samdb, setup_path("provision_basedn.ldif"), {
             "DOMAINDN": names.domaindn,
             "DOMAINSID": str(names.domainsid),
     setup_add_ldif(samdb, setup_path("provision_basedn.ldif"), {
             "DOMAINDN": names.domaindn,
             "DOMAINSID": str(names.domainsid),
@@ -1385,12 +1399,12 @@ def fill_samdb(samdb, lp, names, logger, policyguid,
         "DOMAIN_FUNCTIONALITY": str(domainFunctionality),
         "SAMBA_VERSION_STRING": version,
         "MIN_PWD_LENGTH": str(DEFAULT_MIN_PWD_LENGTH)
         "DOMAIN_FUNCTIONALITY": str(domainFunctionality),
         "SAMBA_VERSION_STRING": version,
         "MIN_PWD_LENGTH": str(DEFAULT_MIN_PWD_LENGTH)
-        })
+    })
 
     # If we are setting up a subdomain, then this has been replicated in, so we don't need to add it
     if fill == FILL_FULL:
         logger.info("Adding configuration container")
 
     # If we are setting up a subdomain, then this has been replicated in, so we don't need to add it
     if fill == FILL_FULL:
         logger.info("Adding configuration container")
-        descr = b64encode(get_config_descriptor(names.domainsid))
+        descr = b64encode(get_config_descriptor(names.domainsid)).decode('utf8')
         setup_add_ldif(samdb, setup_path("provision_configuration_basedn.ldif"), {
                 "CONFIGDN": names.configdn,
                 "DESCRIPTOR": descr,
         setup_add_ldif(samdb, setup_path("provision_configuration_basedn.ldif"), {
                 "CONFIGDN": names.configdn,
                 "DESCRIPTOR": descr,
@@ -1411,8 +1425,8 @@ def fill_samdb(samdb, lp, names, logger, policyguid,
 
     # Now register this container in the root of the forest
     msg = ldb.Message(ldb.Dn(samdb, names.domaindn))
 
     # Now register this container in the root of the forest
     msg = ldb.Message(ldb.Dn(samdb, names.domaindn))
-    msg["subRefs"] = ldb.MessageElement(names.configdn , ldb.FLAG_MOD_ADD,
-                "subRefs")
+    msg["subRefs"] = ldb.MessageElement(names.configdn, ldb.FLAG_MOD_ADD,
+                                        "subRefs")
 
     samdb.invocation_id = invocationid
 
 
     samdb.invocation_id = invocationid
 
@@ -1420,12 +1434,12 @@ def fill_samdb(samdb, lp, names, logger, policyguid,
     if fill == FILL_FULL:
         logger.info("Setting up sam.ldb configuration data")
 
     if fill == FILL_FULL:
         logger.info("Setting up sam.ldb configuration data")
 
-        partitions_descr = b64encode(get_config_partitions_descriptor(names.domainsid))
-        sites_descr = b64encode(get_config_sites_descriptor(names.domainsid))
-        ntdsquotas_descr = b64encode(get_config_ntds_quotas_descriptor(names.domainsid))
-        protected1_descr = b64encode(get_config_delete_protected1_descriptor(names.domainsid))
-        protected1wd_descr = b64encode(get_config_delete_protected1wd_descriptor(names.domainsid))
-        protected2_descr = b64encode(get_config_delete_protected2_descriptor(names.domainsid))
+        partitions_descr = b64encode(get_config_partitions_descriptor(names.domainsid)).decode('utf8')
+        sites_descr = b64encode(get_config_sites_descriptor(names.domainsid)).decode('utf8')
+        ntdsquotas_descr = b64encode(get_config_ntds_quotas_descriptor(names.domainsid)).decode('utf8')
+        protected1_descr = b64encode(get_config_delete_protected1_descriptor(names.domainsid)).decode('utf8')
+        protected1wd_descr = b64encode(get_config_delete_protected1wd_descriptor(names.domainsid)).decode('utf8')
+        protected2_descr = b64encode(get_config_delete_protected2_descriptor(names.domainsid)).decode('utf8')
 
         if "2008" in schema.base_schema:
             # exclude 2012-specific changes if we're using a 2008 schema
 
         if "2008" in schema.base_schema:
             # exclude 2012-specific changes if we're using a 2008 schema
@@ -1456,7 +1470,7 @@ def fill_samdb(samdb, lp, names, logger, policyguid,
 
         setup_add_ldif(samdb, setup_path("extended-rights.ldif"), {
                 "CONFIGDN": names.configdn,
 
         setup_add_ldif(samdb, setup_path("extended-rights.ldif"), {
                 "CONFIGDN": names.configdn,
-                "INC2012" : incl_2012,
+                "INC2012": incl_2012,
                 })
 
         logger.info("Setting up display specifiers")
                 })
 
         logger.info("Setting up display specifiers")
@@ -1469,13 +1483,13 @@ def fill_samdb(samdb, lp, names, logger, policyguid,
 
         logger.info("Modifying display specifiers and extended rights")
         setup_modify_ldif(samdb,
 
         logger.info("Modifying display specifiers and extended rights")
         setup_modify_ldif(samdb,
-            setup_path("provision_configuration_modify.ldif"), {
-            "CONFIGDN": names.configdn,
-            "DISPLAYSPECIFIERS_DESCRIPTOR": protected2_descr
-            })
+                          setup_path("provision_configuration_modify.ldif"), {
+                              "CONFIGDN": names.configdn,
+                              "DISPLAYSPECIFIERS_DESCRIPTOR": protected2_descr
+                          })
 
     logger.info("Adding users container")
 
     logger.info("Adding users container")
-    users_desc = b64encode(get_domain_users_descriptor(names.domainsid))
+    users_desc = b64encode(get_domain_users_descriptor(names.domainsid)).decode('utf8')
     setup_add_ldif(samdb, setup_path("provision_users_add.ldif"), {
             "DOMAINDN": names.domaindn,
             "USERS_DESCRIPTOR": users_desc
     setup_add_ldif(samdb, setup_path("provision_users_add.ldif"), {
             "DOMAINDN": names.domaindn,
             "USERS_DESCRIPTOR": users_desc
@@ -1484,21 +1498,21 @@ def fill_samdb(samdb, lp, names, logger, policyguid,
     setup_modify_ldif(samdb, setup_path("provision_users_modify.ldif"), {
             "DOMAINDN": names.domaindn})
     logger.info("Adding computers container")
     setup_modify_ldif(samdb, setup_path("provision_users_modify.ldif"), {
             "DOMAINDN": names.domaindn})
     logger.info("Adding computers container")
-    computers_desc = b64encode(get_domain_computers_descriptor(names.domainsid))
+    computers_desc = b64encode(get_domain_computers_descriptor(names.domainsid)).decode('utf8')
     setup_add_ldif(samdb, setup_path("provision_computers_add.ldif"), {
             "DOMAINDN": names.domaindn,
             "COMPUTERS_DESCRIPTOR": computers_desc
             })
     logger.info("Modifying computers container")
     setup_modify_ldif(samdb,
     setup_add_ldif(samdb, setup_path("provision_computers_add.ldif"), {
             "DOMAINDN": names.domaindn,
             "COMPUTERS_DESCRIPTOR": computers_desc
             })
     logger.info("Modifying computers container")
     setup_modify_ldif(samdb,
-        setup_path("provision_computers_modify.ldif"), {
-            "DOMAINDN": names.domaindn})
+                      setup_path("provision_computers_modify.ldif"), {
+                          "DOMAINDN": names.domaindn})
     logger.info("Setting up sam.ldb data")
     logger.info("Setting up sam.ldb data")
-    infrastructure_desc = b64encode(get_domain_infrastructure_descriptor(names.domainsid))
-    lostandfound_desc = b64encode(get_domain_delete_protected2_descriptor(names.domainsid))
-    system_desc = b64encode(get_domain_delete_protected1_descriptor(names.domainsid))
-    builtin_desc = b64encode(get_domain_builtin_descriptor(names.domainsid))
-    controllers_desc = b64encode(get_domain_controllers_descriptor(names.domainsid))
+    infrastructure_desc = b64encode(get_domain_infrastructure_descriptor(names.domainsid)).decode('utf8')
+    lostandfound_desc = b64encode(get_domain_delete_protected2_descriptor(names.domainsid)).decode('utf8')
+    system_desc = b64encode(get_domain_delete_protected1_descriptor(names.domainsid)).decode('utf8')
+    builtin_desc = b64encode(get_domain_builtin_descriptor(names.domainsid)).decode('utf8')
+    controllers_desc = b64encode(get_domain_controllers_descriptor(names.domainsid)).decode('utf8')
     setup_add_ldif(samdb, setup_path("provision.ldif"), {
         "CREATTIME": str(samba.unix2nttime(int(time.time()))),
         "DOMAINDN": names.domaindn,
     setup_add_ldif(samdb, setup_path("provision.ldif"), {
         "CREATTIME": str(samba.unix2nttime(int(time.time()))),
         "DOMAINDN": names.domaindn,
@@ -1513,22 +1527,22 @@ def fill_samdb(samdb, lp, names, logger, policyguid,
         "SYSTEM_DESCRIPTOR": system_desc,
         "BUILTIN_DESCRIPTOR": builtin_desc,
         "DOMAIN_CONTROLLERS_DESCRIPTOR": controllers_desc,
         "SYSTEM_DESCRIPTOR": system_desc,
         "BUILTIN_DESCRIPTOR": builtin_desc,
         "DOMAIN_CONTROLLERS_DESCRIPTOR": controllers_desc,
-        })
+    })
 
     # If we are setting up a subdomain, then this has been replicated in, so we don't need to add it
     if fill == FILL_FULL:
 
     # If we are setting up a subdomain, then this has been replicated in, so we don't need to add it
     if fill == FILL_FULL:
-        managedservice_descr = b64encode(get_managed_service_accounts_descriptor(names.domainsid))
+        managedservice_descr = b64encode(get_managed_service_accounts_descriptor(names.domainsid)).decode('utf8')
         setup_modify_ldif(samdb,
                           setup_path("provision_configuration_references.ldif"), {
         setup_modify_ldif(samdb,
                           setup_path("provision_configuration_references.ldif"), {
-                "CONFIGDN": names.configdn,
-                "SCHEMADN": names.schemadn})
+                              "CONFIGDN": names.configdn,
+                              "SCHEMADN": names.schemadn})
 
         logger.info("Setting up well known security principals")
 
         logger.info("Setting up well known security principals")
-        protected1wd_descr = b64encode(get_config_delete_protected1wd_descriptor(names.domainsid))
+        protected1wd_descr = b64encode(get_config_delete_protected1wd_descriptor(names.domainsid)).decode('utf8')
         setup_add_ldif(samdb, setup_path("provision_well_known_sec_princ.ldif"), {
             "CONFIGDN": names.configdn,
             "WELLKNOWNPRINCIPALS_DESCRIPTOR": protected1wd_descr,
         setup_add_ldif(samdb, setup_path("provision_well_known_sec_princ.ldif"), {
             "CONFIGDN": names.configdn,
             "WELLKNOWNPRINCIPALS_DESCRIPTOR": protected1wd_descr,
-            }, controls=["relax:0", "provision:0"])
+        }, controls=["relax:0", "provision:0"])
 
     if fill == FILL_FULL or fill == FILL_SUBDOMAIN:
         setup_modify_ldif(samdb,
 
     if fill == FILL_FULL or fill == FILL_SUBDOMAIN:
         setup_modify_ldif(samdb,
@@ -1541,45 +1555,46 @@ def fill_samdb(samdb, lp, names, logger, policyguid,
         setup_add_ldif(samdb, setup_path("provision_users.ldif"), {
             "DOMAINDN": names.domaindn,
             "DOMAINSID": str(names.domainsid),
         setup_add_ldif(samdb, setup_path("provision_users.ldif"), {
             "DOMAINDN": names.domaindn,
             "DOMAINSID": str(names.domainsid),
-            "ADMINPASS_B64": b64encode(adminpass.encode('utf-16-le')),
-            "KRBTGTPASS_B64": b64encode(krbtgtpass.encode('utf-16-le'))
-            }, controls=["relax:0", "provision:0"])
+            "ADMINPASS_B64": b64encode(adminpass.encode('utf-16-le')).decode('utf8'),
+            "KRBTGTPASS_B64": b64encode(krbtgtpass.encode('utf-16-le')).decode('utf8')
+        }, controls=["relax:0", "provision:0"])
 
         logger.info("Setting up self join")
         setup_self_join(samdb, admin_session_info, names=names, fill=fill,
 
         logger.info("Setting up self join")
         setup_self_join(samdb, admin_session_info, names=names, fill=fill,
-            invocationid=invocationid,
-            dns_backend=dns_backend,
-            dnspass=dnspass,
-            machinepass=machinepass,
-            domainsid=names.domainsid,
-            next_rid=next_rid,
-            dc_rid=dc_rid,
-            policyguid=policyguid,
-            policyguid_dc=policyguid_dc,
-            domainControllerFunctionality=domainControllerFunctionality,
-            ntdsguid=ntdsguid)
+                        invocationid=invocationid,
+                        dns_backend=dns_backend,
+                        dnspass=dnspass,
+                        machinepass=machinepass,
+                        domainsid=names.domainsid,
+                        next_rid=next_rid,
+                        dc_rid=dc_rid,
+                        policyguid=policyguid,
+                        policyguid_dc=policyguid_dc,
+                        domainControllerFunctionality=domainControllerFunctionality,
+                        ntdsguid=ntdsguid)
 
         ntds_dn = "CN=NTDS Settings,%s" % names.serverdn
         names.ntdsguid = samdb.searchone(basedn=ntds_dn,
 
         ntds_dn = "CN=NTDS Settings,%s" % names.serverdn
         names.ntdsguid = samdb.searchone(basedn=ntds_dn,
-            attribute="objectGUID", expression="", scope=ldb.SCOPE_BASE)
-        assert isinstance(names.ntdsguid, str)
+                                         attribute="objectGUID", expression="", scope=ldb.SCOPE_BASE).decode('utf8')
+        assert isinstance(names.ntdsguid, string_types)
 
     return samdb
 
 
 SYSVOL_ACL = "O:LAG:BAD:P(A;OICI;0x001f01ff;;;BA)(A;OICI;0x001200a9;;;SO)(A;OICI;0x001f01ff;;;SY)(A;OICI;0x001200a9;;;AU)"
 POLICIES_ACL = "O:LAG:BAD:P(A;OICI;0x001f01ff;;;BA)(A;OICI;0x001200a9;;;SO)(A;OICI;0x001f01ff;;;SY)(A;OICI;0x001200a9;;;AU)(A;OICI;0x001301bf;;;PA)"
 
     return samdb
 
 
 SYSVOL_ACL = "O:LAG:BAD:P(A;OICI;0x001f01ff;;;BA)(A;OICI;0x001200a9;;;SO)(A;OICI;0x001f01ff;;;SY)(A;OICI;0x001200a9;;;AU)"
 POLICIES_ACL = "O:LAG:BAD:P(A;OICI;0x001f01ff;;;BA)(A;OICI;0x001200a9;;;SO)(A;OICI;0x001f01ff;;;SY)(A;OICI;0x001200a9;;;AU)(A;OICI;0x001301bf;;;PA)"
-SYSVOL_SERVICE="sysvol"
+SYSVOL_SERVICE = "sysvol"
+
 
 def set_dir_acl(path, acl, lp, domsid, use_ntvfs, passdb, service=SYSVOL_SERVICE):
     setntacl(lp, path, acl, domsid, use_ntvfs=use_ntvfs, skip_invalid_chown=True, passdb=passdb, service=service)
     for root, dirs, files in os.walk(path, topdown=False):
         for name in files:
             setntacl(lp, os.path.join(root, name), acl, domsid,
 
 def set_dir_acl(path, acl, lp, domsid, use_ntvfs, passdb, service=SYSVOL_SERVICE):
     setntacl(lp, path, acl, domsid, use_ntvfs=use_ntvfs, skip_invalid_chown=True, passdb=passdb, service=service)
     for root, dirs, files in os.walk(path, topdown=False):
         for name in files:
             setntacl(lp, os.path.join(root, name), acl, domsid,
-                    use_ntvfs=use_ntvfs, skip_invalid_chown=True, passdb=passdb, service=service)
+                     use_ntvfs=use_ntvfs, skip_invalid_chown=True, passdb=passdb, service=service)
         for name in dirs:
             setntacl(lp, os.path.join(root, name), acl, domsid,
         for name in dirs:
             setntacl(lp, os.path.join(root, name), acl, domsid,
-                    use_ntvfs=use_ntvfs, skip_invalid_chown=True, passdb=passdb, service=service)
+                     use_ntvfs=use_ntvfs, skip_invalid_chown=True, passdb=passdb, service=service)
 
 
 def set_gpos_acl(sysvol, dnsdomain, domainsid, domaindn, samdb, lp, use_ntvfs, passdb):
 
 
 def set_gpos_acl(sysvol, dnsdomain, domainsid, domaindn, samdb, lp, use_ntvfs, passdb):
@@ -1597,15 +1612,15 @@ def set_gpos_acl(sysvol, dnsdomain, domainsid, domaindn, samdb, lp, use_ntvfs, p
     # Set ACL for GPO root folder
     root_policy_path = os.path.join(sysvol, dnsdomain, "Policies")
     setntacl(lp, root_policy_path, POLICIES_ACL, str(domainsid),
     # Set ACL for GPO root folder
     root_policy_path = os.path.join(sysvol, dnsdomain, "Policies")
     setntacl(lp, root_policy_path, POLICIES_ACL, str(domainsid),
-            use_ntvfs=use_ntvfs, skip_invalid_chown=True, passdb=passdb, service=SYSVOL_SERVICE)
+             use_ntvfs=use_ntvfs, skip_invalid_chown=True, passdb=passdb, service=SYSVOL_SERVICE)
 
 
-    res = samdb.search(base="CN=Policies,CN=System,%s"%(domaindn),
-                        attrs=["cn", "nTSecurityDescriptor"],
-                        expression="", scope=ldb.SCOPE_ONELEVEL)
+    res = samdb.search(base="CN=Policies,CN=System,%s" %(domaindn),
+                       attrs=["cn", "nTSecurityDescriptor"],
+                       expression="", scope=ldb.SCOPE_ONELEVEL)
 
     for policy in res:
         acl = ndr_unpack(security.descriptor,
 
     for policy in res:
         acl = ndr_unpack(security.descriptor,
-                         str(policy["nTSecurityDescriptor"])).as_sddl()
+                         policy["nTSecurityDescriptor"][0]).as_sddl()
         policy_path = getpolicypath(sysvol, dnsdomain, str(policy["cn"]))
         set_dir_acl(policy_path, dsacl2fsacl(acl, domainsid), lp,
                     str(domainsid), use_ntvfs,
         policy_path = getpolicypath(sysvol, dnsdomain, str(policy["cn"]))
         set_dir_acl(policy_path, dsacl2fsacl(acl, domainsid), lp,
                     str(domainsid), use_ntvfs,
@@ -1613,7 +1628,7 @@ def set_gpos_acl(sysvol, dnsdomain, domainsid, domaindn, samdb, lp, use_ntvfs, p
 
 
 def setsysvolacl(samdb, netlogon, sysvol, uid, gid, domainsid, dnsdomain,
 
 
 def setsysvolacl(samdb, netlogon, sysvol, uid, gid, domainsid, dnsdomain,
-        domaindn, lp, use_ntvfs):
+                 domaindn, lp, use_ntvfs):
     """Set the ACL for the sysvol share and the subfolders
 
     :param samdb: An LDB object on the SAM db
     """Set the ACL for the sysvol share and the subfolders
 
     :param samdb: An LDB object on the SAM db
@@ -1676,7 +1691,6 @@ def setsysvolacl(samdb, netlogon, sysvol, uid, gid, domainsid, dnsdomain,
         if domain_info["dns_domain"].upper() != dnsdomain.upper():
             raise ProvisioningError('Realm as seen by pdb_samba_dsdb [%s] does not match Realm as seen by the provision script [%s]!' % (domain_info["dns_domain"].upper(), dnsdomain.upper()))
 
         if domain_info["dns_domain"].upper() != dnsdomain.upper():
             raise ProvisioningError('Realm as seen by pdb_samba_dsdb [%s] does not match Realm as seen by the provision script [%s]!' % (domain_info["dns_domain"].upper(), dnsdomain.upper()))
 
-
     try:
         if use_ntvfs:
             os.chown(sysvol, -1, gid)
     try:
         if use_ntvfs:
             os.chown(sysvol, -1, gid)
@@ -1685,33 +1699,47 @@ def setsysvolacl(samdb, netlogon, sysvol, uid, gid, domainsid, dnsdomain,
     else:
         canchown = True
 
     else:
         canchown = True
 
+    # use admin sid dn as user dn, since admin should own most of the files,
+    # the operation will be much faster
+    userdn = '<SID={}-{}>'.format(domainsid, security.DOMAIN_RID_ADMINISTRATOR)
+
+    flags = (auth.AUTH_SESSION_INFO_DEFAULT_GROUPS |
+             auth.AUTH_SESSION_INFO_AUTHENTICATED |
+             auth.AUTH_SESSION_INFO_SIMPLE_PRIVILEGES)
+
+    session_info = auth.user_session(samdb, lp_ctx=lp, dn=userdn,
+                                     session_info_flags=flags)
+
+    def _setntacl(path):
+        """A helper to reuse args"""
+        return setntacl(
+            lp, path, SYSVOL_ACL, str(domainsid),
+            use_ntvfs=use_ntvfs, skip_invalid_chown=True, passdb=s4_passdb,
+            service=SYSVOL_SERVICE, session_info=session_info)
+
     # Set the SYSVOL_ACL on the sysvol folder and subfolder (first level)
     # Set the SYSVOL_ACL on the sysvol folder and subfolder (first level)
-    setntacl(lp,sysvol, SYSVOL_ACL, str(domainsid), use_ntvfs=use_ntvfs,
-             skip_invalid_chown=True, passdb=s4_passdb,
-             service=SYSVOL_SERVICE)
+    _setntacl(sysvol)
     for root, dirs, files in os.walk(sysvol, topdown=False):
         for name in files:
             if use_ntvfs and canchown:
                 os.chown(os.path.join(root, name), -1, gid)
     for root, dirs, files in os.walk(sysvol, topdown=False):
         for name in files:
             if use_ntvfs and canchown:
                 os.chown(os.path.join(root, name), -1, gid)
-            setntacl(lp, os.path.join(root, name), SYSVOL_ACL, str(domainsid),
-                     use_ntvfs=use_ntvfs, skip_invalid_chown=True,
-                     passdb=s4_passdb, service=SYSVOL_SERVICE)
+            _setntacl(os.path.join(root, name))
         for name in dirs:
             if use_ntvfs and canchown:
                 os.chown(os.path.join(root, name), -1, gid)
         for name in dirs:
             if use_ntvfs and canchown:
                 os.chown(os.path.join(root, name), -1, gid)
-            setntacl(lp, os.path.join(root, name), SYSVOL_ACL, str(domainsid),
-                     use_ntvfs=use_ntvfs, skip_invalid_chown=True,
-                     passdb=s4_passdb, service=SYSVOL_SERVICE)
+            _setntacl(os.path.join(root, name))
 
     # Set acls on Policy folder and policies folders
     set_gpos_acl(sysvol, dnsdomain, domainsid, domaindn, samdb, lp, use_ntvfs, passdb=s4_passdb)
 
 
     # Set acls on Policy folder and policies folders
     set_gpos_acl(sysvol, dnsdomain, domainsid, domaindn, samdb, lp, use_ntvfs, passdb=s4_passdb)
 
+
 def acl_type(direct_db_access):
     if direct_db_access:
         return "DB"
     else:
         return "VFS"
 
 def acl_type(direct_db_access):
     if direct_db_access:
         return "DB"
     else:
         return "VFS"
 
+
 def check_dir_acl(path, acl, lp, domainsid, direct_db_access):
     fsacl = getntacl(lp, path, direct_db_access=direct_db_access, service=SYSVOL_SERVICE)
     fsacl_sddl = fsacl.as_sddl(domainsid)
 def check_dir_acl(path, acl, lp, domainsid, direct_db_access):
     fsacl = getntacl(lp, path, direct_db_access=direct_db_access, service=SYSVOL_SERVICE)
     fsacl_sddl = fsacl.as_sddl(domainsid)
@@ -1723,7 +1751,9 @@ def check_dir_acl(path, acl, lp, domainsid, direct_db_access):
             fsacl = getntacl(lp, os.path.join(root, name),
                              direct_db_access=direct_db_access, service=SYSVOL_SERVICE)
             if fsacl is None:
             fsacl = getntacl(lp, os.path.join(root, name),
                              direct_db_access=direct_db_access, service=SYSVOL_SERVICE)
             if fsacl is None:
-                raise ProvisioningError('%s ACL on GPO file %s %s not found!' % (acl_type(direct_db_access), os.path.join(root, name)))
+                raise ProvisioningError('%s ACL on GPO file %s not found!' %
+                                        (acl_type(direct_db_access),
+                                         os.path.join(root, name)))
             fsacl_sddl = fsacl.as_sddl(domainsid)
             if fsacl_sddl != acl:
                 raise ProvisioningError('%s ACL on GPO file %s %s does not match expected value %s from GPO object' % (acl_type(direct_db_access), os.path.join(root, name), fsacl_sddl, acl))
             fsacl_sddl = fsacl.as_sddl(domainsid)
             if fsacl_sddl != acl:
                 raise ProvisioningError('%s ACL on GPO file %s %s does not match expected value %s from GPO object' % (acl_type(direct_db_access), os.path.join(root, name), fsacl_sddl, acl))
@@ -1732,14 +1762,16 @@ def check_dir_acl(path, acl, lp, domainsid, direct_db_access):
             fsacl = getntacl(lp, os.path.join(root, name),
                              direct_db_access=direct_db_access, service=SYSVOL_SERVICE)
             if fsacl is None:
             fsacl = getntacl(lp, os.path.join(root, name),
                              direct_db_access=direct_db_access, service=SYSVOL_SERVICE)
             if fsacl is None:
-                raise ProvisioningError('%s ACL on GPO directory %s %s not found!' % (acl_type(direct_db_access), os.path.join(root, name)))
+                raise ProvisioningError('%s ACL on GPO directory %s not found!'
+                                        % (acl_type(direct_db_access),
+                                           os.path.join(root, name)))
             fsacl_sddl = fsacl.as_sddl(domainsid)
             if fsacl_sddl != acl:
                 raise ProvisioningError('%s ACL on GPO directory %s %s does not match expected value %s from GPO object' % (acl_type(direct_db_access), os.path.join(root, name), fsacl_sddl, acl))
 
 
 def check_gpos_acl(sysvol, dnsdomain, domainsid, domaindn, samdb, lp,
             fsacl_sddl = fsacl.as_sddl(domainsid)
             if fsacl_sddl != acl:
                 raise ProvisioningError('%s ACL on GPO directory %s %s does not match expected value %s from GPO object' % (acl_type(direct_db_access), os.path.join(root, name), fsacl_sddl, acl))
 
 
 def check_gpos_acl(sysvol, dnsdomain, domainsid, domaindn, samdb, lp,
-        direct_db_access):
+                   direct_db_access):
     """Set ACL on the sysvol/<dnsname>/Policies folder and the policy
     folders beneath.
 
     """Set ACL on the sysvol/<dnsname>/Policies folder and the policy
     folders beneath.
 
@@ -1760,20 +1792,20 @@ def check_gpos_acl(sysvol, dnsdomain, domainsid, domaindn, samdb, lp,
     fsacl_sddl = fsacl.as_sddl(domainsid)
     if fsacl_sddl != POLICIES_ACL:
         raise ProvisioningError('%s ACL on policy root %s %s does not match expected value %s from provision' % (acl_type(direct_db_access), root_policy_path, fsacl_sddl, fsacl))
     fsacl_sddl = fsacl.as_sddl(domainsid)
     if fsacl_sddl != POLICIES_ACL:
         raise ProvisioningError('%s ACL on policy root %s %s does not match expected value %s from provision' % (acl_type(direct_db_access), root_policy_path, fsacl_sddl, fsacl))
-    res = samdb.search(base="CN=Policies,CN=System,%s"%(domaindn),
-                        attrs=["cn", "nTSecurityDescriptor"],
-                        expression="", scope=ldb.SCOPE_ONELEVEL)
+    res = samdb.search(base="CN=Policies,CN=System,%s" %(domaindn),
+                       attrs=["cn", "nTSecurityDescriptor"],
+                       expression="", scope=ldb.SCOPE_ONELEVEL)
 
     for policy in res:
         acl = ndr_unpack(security.descriptor,
 
     for policy in res:
         acl = ndr_unpack(security.descriptor,
-                         str(policy["nTSecurityDescriptor"])).as_sddl()
+                         policy["nTSecurityDescriptor"][0]).as_sddl()
         policy_path = getpolicypath(sysvol, dnsdomain, str(policy["cn"]))
         check_dir_acl(policy_path, dsacl2fsacl(acl, domainsid), lp,
                       domainsid, direct_db_access)
 
 
 def checksysvolacl(samdb, netlogon, sysvol, domainsid, dnsdomain, domaindn,
         policy_path = getpolicypath(sysvol, dnsdomain, str(policy["cn"]))
         check_dir_acl(policy_path, dsacl2fsacl(acl, domainsid), lp,
                       domainsid, direct_db_access)
 
 
 def checksysvolacl(samdb, netlogon, sysvol, domainsid, dnsdomain, domaindn,
-    lp):
+                   lp):
     """Set the ACL for the sysvol share and the subfolders
 
     :param samdb: An LDB object on the SAM db
     """Set the ACL for the sysvol share and the subfolders
 
     :param samdb: An LDB object on the SAM db
@@ -1818,7 +1850,7 @@ def checksysvolacl(samdb, netlogon, sysvol, domainsid, dnsdomain, domaindn,
 
         # Check acls on Policy folder and policies folders
         check_gpos_acl(sysvol, dnsdomain, domainsid, domaindn, samdb, lp,
 
         # Check acls on Policy folder and policies folders
         check_gpos_acl(sysvol, dnsdomain, domainsid, domaindn, samdb, lp,
-                direct_db_access)
+                       direct_db_access)
 
 
 def interface_ips_v4(lp):
 
 
 def interface_ips_v4(lp):
@@ -1876,15 +1908,15 @@ def provision_fill(samdb, secrets_ldb, logger, names, paths,
     samdb.transaction_start()
     try:
         samdb = fill_samdb(samdb, lp, names, logger=logger,
     samdb.transaction_start()
     try:
         samdb = fill_samdb(samdb, lp, names, logger=logger,
-                       schema=schema,
-                       policyguid=policyguid, policyguid_dc=policyguid_dc,
-                       fill=samdb_fill, adminpass=adminpass, krbtgtpass=krbtgtpass,
-                       invocationid=invocationid, machinepass=machinepass,
-                       dns_backend=dns_backend, dnspass=dnspass,
-                       ntdsguid=ntdsguid, serverrole=serverrole,
-                       dom_for_fun_level=dom_for_fun_level, am_rodc=am_rodc,
-                       next_rid=next_rid, dc_rid=dc_rid,
-                       backend_store=backend_store)
+                           schema=schema,
+                           policyguid=policyguid, policyguid_dc=policyguid_dc,
+                           fill=samdb_fill, adminpass=adminpass, krbtgtpass=krbtgtpass,
+                           invocationid=invocationid, machinepass=machinepass,
+                           dns_backend=dns_backend, dnspass=dnspass,
+                           ntdsguid=ntdsguid, serverrole=serverrole,
+                           dom_for_fun_level=dom_for_fun_level, am_rodc=am_rodc,
+                           next_rid=next_rid, dc_rid=dc_rid,
+                           backend_store=backend_store)
 
         # Set up group policies (domain policy and domain controller
         # policy)
 
         # Set up group policies (domain policy and domain controller
         # policy)
@@ -1908,9 +1940,9 @@ def provision_fill(samdb, secrets_ldb, logger, names, paths,
             logger.info("Setting acl on sysvol skipped")
 
         secretsdb_self_join(secrets_ldb, domain=names.domain,
             logger.info("Setting acl on sysvol skipped")
 
         secretsdb_self_join(secrets_ldb, domain=names.domain,
-                realm=names.realm, dnsdomain=names.dnsdomain,
-                netbiosname=names.netbiosname, domainsid=names.domainsid,
-                machinepass=machinepass, secure_channel_type=SEC_CHAN_BDC)
+                            realm=names.realm, dnsdomain=names.dnsdomain,
+                            netbiosname=names.netbiosname, domainsid=names.domainsid,
+                            machinepass=machinepass, secure_channel_type=SEC_CHAN_BDC)
 
         # Now set up the right msDS-SupportedEncryptionTypes into the DB
         # In future, this might be determined from some configuration
 
         # Now set up the right msDS-SupportedEncryptionTypes into the DB
         # In future, this might be determined from some configuration
@@ -1938,8 +1970,8 @@ def provision_fill(samdb, secrets_ldb, logger, names, paths,
                      backend_store=backend_store)
 
         domainguid = samdb.searchone(basedn=samdb.get_default_basedn(),
                      backend_store=backend_store)
 
         domainguid = samdb.searchone(basedn=samdb.get_default_basedn(),
-                                     attribute="objectGUID")
-        assert isinstance(domainguid, str)
+                                     attribute="objectGUID").decode('utf8')
+        assert isinstance(domainguid, string_types)
 
     lastProvisionUSNs = get_last_provision_usn(samdb)
     maxUSN = get_max_usn(samdb, str(names.rootdn))
 
     lastProvisionUSNs = get_last_provision_usn(samdb)
     maxUSN = get_max_usn(samdb, str(names.rootdn))
@@ -1950,12 +1982,12 @@ def provision_fill(samdb, secrets_ldb, logger, names, paths,
 
     logger.info("Setting up sam.ldb rootDSE marking as synchronized")
     setup_modify_ldif(samdb, setup_path("provision_rootdse_modify.ldif"),
 
     logger.info("Setting up sam.ldb rootDSE marking as synchronized")
     setup_modify_ldif(samdb, setup_path("provision_rootdse_modify.ldif"),
-                      { 'NTDSGUID' : names.ntdsguid })
+                      {'NTDSGUID': names.ntdsguid})
 
     # fix any dangling GUIDs from the provision
     logger.info("Fixing provision GUIDs")
     chk = dbcheck(samdb, samdb_schema=samdb, verbose=False, fix=True, yes=True,
 
     # fix any dangling GUIDs from the provision
     logger.info("Fixing provision GUIDs")
     chk = dbcheck(samdb, samdb_schema=samdb, verbose=False, fix=True, yes=True,
-            quiet=True)
+                  quiet=True)
     samdb.transaction_start()
     try:
         # a small number of GUIDs are missing because of ordering issues in the
     samdb.transaction_start()
     try:
         # a small number of GUIDs are missing because of ordering issues in the
@@ -1972,7 +2004,7 @@ def provision_fill(samdb, secrets_ldb, logger, names, paths,
                                   'ipsecNegotiationPolicyReference',
                                   'ipsecNFAReference'])
         if chk.check_database(DN=names.schemadn, scope=ldb.SCOPE_SUBTREE,
                                   'ipsecNegotiationPolicyReference',
                                   'ipsecNFAReference'])
         if chk.check_database(DN=names.schemadn, scope=ldb.SCOPE_SUBTREE,
-                attrs=['attributeId', 'governsId']) != 0:
+                              attrs=['attributeId', 'governsId']) != 0:
             raise ProvisioningError("Duplicate attributeId or governsId in schema. Must be fixed manually!!")
     except:
         samdb.transaction_cancel()
             raise ProvisioningError("Duplicate attributeId or governsId in schema. Must be fixed manually!!")
     except:
         samdb.transaction_cancel()
@@ -1993,7 +2025,7 @@ _ROLES_MAP = {
     "member server": "member server",
     "standalone": "standalone server",
     "standalone server": "standalone server",
     "member server": "member server",
     "standalone": "standalone server",
     "standalone server": "standalone server",
-    }
+}
 
 
 def sanitize_server_role(role):
 
 
 def sanitize_server_role(role):
@@ -2011,7 +2043,7 @@ def sanitize_server_role(role):
 
 
 def provision_fake_ypserver(logger, samdb, domaindn, netbiosname, nisdomain,
 
 
 def provision_fake_ypserver(logger, samdb, domaindn, netbiosname, nisdomain,
-        maxuid, maxgid):
+                            maxuid, maxgid):
     """Create AD entries for the fake ypserver.
 
     This is needed for being able to manipulate posix attrs via ADUC.
     """Create AD entries for the fake ypserver.
 
     This is needed for being able to manipulate posix attrs via ADUC.
@@ -2020,16 +2052,17 @@ def provision_fake_ypserver(logger, samdb, domaindn, netbiosname, nisdomain,
     try:
         logger.info("Setting up fake yp server settings")
         setup_add_ldif(samdb, setup_path("ypServ30.ldif"), {
     try:
         logger.info("Setting up fake yp server settings")
         setup_add_ldif(samdb, setup_path("ypServ30.ldif"), {
-        "DOMAINDN": domaindn,
-        "NETBIOSNAME": netbiosname,
-        "NISDOMAIN": nisdomain,
-         })
+            "DOMAINDN": domaindn,
+            "NETBIOSNAME": netbiosname,
+            "NISDOMAIN": nisdomain,
+        })
     except:
         samdb.transaction_cancel()
         raise
     else:
         samdb.transaction_commit()
 
     except:
         samdb.transaction_cancel()
         raise
     else:
         samdb.transaction_commit()
 
+
 def directory_create_or_exists(path, mode=0o755):
     if not os.path.exists(path):
         try:
 def directory_create_or_exists(path, mode=0o755):
     if not os.path.exists(path):
         try:
@@ -2040,22 +2073,54 @@ def directory_create_or_exists(path, mode=0o755):
             else:
                 raise ProvisioningError("Failed to create directory %s: %s" % (path, e.strerror))
 
             else:
                 raise ProvisioningError("Failed to create directory %s: %s" % (path, e.strerror))
 
+
+def determine_host_ip(logger, lp, hostip=None):
+    if hostip is None:
+        logger.info("Looking up IPv4 addresses")
+        hostips = interface_ips_v4(lp)
+        if len(hostips) > 0:
+            hostip = hostips[0]
+            if len(hostips) > 1:
+                logger.warning("More than one IPv4 address found. Using %s",
+                               hostip)
+    if hostip == "127.0.0.1":
+        hostip = None
+    if hostip is None:
+        logger.warning("No IPv4 address will be assigned")
+
+    return hostip
+
+
+def determine_host_ip6(logger, lp, hostip6=None):
+    if hostip6 is None:
+        logger.info("Looking up IPv6 addresses")
+        hostips = interface_ips_v6(lp)
+        if hostips:
+            hostip6 = hostips[0]
+        if len(hostips) > 1:
+            logger.warning("More than one IPv6 address found. Using %s", hostip6)
+    if hostip6 is None:
+        logger.warning("No IPv6 address will be assigned")
+
+    return hostip6
+
+
 def provision(logger, session_info, smbconf=None,
 def provision(logger, session_info, smbconf=None,
-        targetdir=None, samdb_fill=FILL_FULL, realm=None, rootdn=None,
-        domaindn=None, schemadn=None, configdn=None, serverdn=None,
-        domain=None, hostname=None, hostip=None, hostip6=None, domainsid=None,
-        next_rid=1000, dc_rid=None, adminpass=None, ldapadminpass=None,
-        krbtgtpass=None, domainguid=None, policyguid=None, policyguid_dc=None,
-        dns_backend=None, dns_forwarder=None, dnspass=None,
-        invocationid=None, machinepass=None, ntdsguid=None,
-        root=None, nobody=None, users=None, backup=None, aci=None,
-        serverrole=None, dom_for_fun_level=None, backend_type=None,
-        sitename=None, ol_mmr_urls=None, ol_olc=None, slapd_path=None,
-        useeadb=False, am_rodc=False, lp=None, use_ntvfs=False,
-        use_rfc2307=False, maxuid=None, maxgid=None, skip_sysvolacl=True,
-        ldap_backend_forced_uri=None, nosync=False, ldap_dryrun_mode=False,
-        ldap_backend_extra_port=None, base_schema=None,
-        plaintext_secrets=False, backend_store=None):
+              targetdir=None, samdb_fill=FILL_FULL, realm=None, rootdn=None,
+              domaindn=None, schemadn=None, configdn=None, serverdn=None,
+              domain=None, hostname=None, hostip=None, hostip6=None, domainsid=None,
+              next_rid=1000, dc_rid=None, adminpass=None, ldapadminpass=None,
+              krbtgtpass=None, domainguid=None, policyguid=None, policyguid_dc=None,
+              dns_backend=None, dns_forwarder=None, dnspass=None,
+              invocationid=None, machinepass=None, ntdsguid=None,
+              root=None, nobody=None, users=None, backup=None, aci=None,
+              serverrole=None, dom_for_fun_level=None, backend_type=None,
+              sitename=None, ol_mmr_urls=None, ol_olc=None, slapd_path=None,
+              useeadb=False, am_rodc=False, lp=None, use_ntvfs=False,
+              use_rfc2307=False, maxuid=None, maxgid=None, skip_sysvolacl=True,
+              ldap_backend_forced_uri=None, nosync=False, ldap_dryrun_mode=False,
+              ldap_backend_extra_port=None, base_schema=None,
+              plaintext_secrets=False, backend_store=None):
     """Provision samba4
 
     :note: caution, this wipes all existing data!
     """Provision samba4
 
     :note: caution, this wipes all existing data!
@@ -2138,38 +2203,17 @@ def provision(logger, session_info, smbconf=None,
         lp = samba.param.LoadParm()
     lp.load(smbconf)
     names = guess_names(lp=lp, hostname=hostname, domain=domain,
         lp = samba.param.LoadParm()
     lp.load(smbconf)
     names = guess_names(lp=lp, hostname=hostname, domain=domain,
-        dnsdomain=realm, serverrole=serverrole, domaindn=domaindn,
-        configdn=configdn, schemadn=schemadn, serverdn=serverdn,
-        sitename=sitename, rootdn=rootdn, domain_names_forced=(samdb_fill == FILL_DRS))
+                        dnsdomain=realm, serverrole=serverrole, domaindn=domaindn,
+                        configdn=configdn, schemadn=schemadn, serverdn=serverdn,
+                        sitename=sitename, rootdn=rootdn, domain_names_forced=(samdb_fill == FILL_DRS))
     paths = provision_paths_from_lp(lp, names.dnsdomain)
 
     paths.bind_gid = bind_gid
     paths = provision_paths_from_lp(lp, names.dnsdomain)
 
     paths.bind_gid = bind_gid
-    paths.root_uid = root_uid;
+    paths.root_uid = root_uid
     paths.root_gid = root_gid
 
     paths.root_gid = root_gid
 
-    if hostip is None:
-        logger.info("Looking up IPv4 addresses")
-        hostips = interface_ips_v4(lp)
-        if len(hostips) > 0:
-            hostip = hostips[0]
-            if len(hostips) > 1:
-                logger.warning("More than one IPv4 address found. Using %s",
-                    hostip)
-    if hostip == "127.0.0.1":
-        hostip = None
-    if hostip is None:
-        logger.warning("No IPv4 address will be assigned")
-
-    if hostip6 is None:
-        logger.info("Looking up IPv6 addresses")
-        hostips = interface_ips_v6(lp)
-        if hostips:
-            hostip6 = hostips[0]
-        if len(hostips) > 1:
-            logger.warning("More than one IPv6 address found. Using %s", hostip6)
-    if hostip6 is None:
-        logger.warning("No IPv6 address will be assigned")
-
+    hostip = determine_host_ip(logger, lp, hostip)
+    hostip6 = determine_host_ip6(logger, lp, hostip6)
     names.hostip = hostip
     names.hostip6 = hostip6
     names.domainguid = domainguid
     names.hostip = hostip
     names.hostip6 = hostip6
     names.domainguid = domainguid
@@ -2192,35 +2236,28 @@ def provision(logger, session_info, smbconf=None,
     ldapi_url = "ldapi://%s" % urllib_quote(paths.s4_ldapi_path, safe="")
 
     schema = Schema(domainsid, invocationid=invocationid,
     ldapi_url = "ldapi://%s" % urllib_quote(paths.s4_ldapi_path, safe="")
 
     schema = Schema(domainsid, invocationid=invocationid,
-        schemadn=names.schemadn, base_schema=base_schema)
+                    schemadn=names.schemadn, base_schema=base_schema)
 
     if backend_type == "ldb":
         provision_backend = LDBBackend(backend_type, paths=paths,
 
     if backend_type == "ldb":
         provision_backend = LDBBackend(backend_type, paths=paths,
-            lp=lp,
-            names=names, logger=logger)
-    elif backend_type == "existing":
-        # If support for this is ever added back, then the URI will need to be
-        # specified again
-        provision_backend = ExistingBackend(backend_type, paths=paths,
-            lp=lp,
-            names=names, logger=logger,
-            ldap_backend_forced_uri=ldap_backend_forced_uri)
+                                       lp=lp,
+                                       names=names, logger=logger)
     elif backend_type == "fedora-ds":
         provision_backend = FDSBackend(backend_type, paths=paths,
     elif backend_type == "fedora-ds":
         provision_backend = FDSBackend(backend_type, paths=paths,
-            lp=lp,
-            names=names, logger=logger, domainsid=domainsid,
-            schema=schema, hostname=hostname, ldapadminpass=ldapadminpass,
-            slapd_path=slapd_path,
-            root=root)
+                                       lp=lp,
+                                       names=names, logger=logger, domainsid=domainsid,
+                                       schema=schema, hostname=hostname, ldapadminpass=ldapadminpass,
+                                       slapd_path=slapd_path,
+                                       root=root)
     elif backend_type == "openldap":
         provision_backend = OpenLDAPBackend(backend_type, paths=paths,
     elif backend_type == "openldap":
         provision_backend = OpenLDAPBackend(backend_type, paths=paths,
-            lp=lp,
-            names=names, logger=logger, domainsid=domainsid,
-            schema=schema, hostname=hostname, ldapadminpass=ldapadminpass,
-            slapd_path=slapd_path, ol_mmr_urls=ol_mmr_urls,
-            ldap_backend_extra_port=ldap_backend_extra_port,
-            ldap_dryrun_mode=ldap_dryrun_mode, nosync=nosync,
-            ldap_backend_forced_uri=ldap_backend_forced_uri)
+                                            lp=lp,
+                                            names=names, logger=logger, domainsid=domainsid,
+                                            schema=schema, hostname=hostname, ldapadminpass=ldapadminpass,
+                                            slapd_path=slapd_path, ol_mmr_urls=ol_mmr_urls,
+                                            ldap_backend_extra_port=ldap_backend_extra_port,
+                                            ldap_dryrun_mode=ldap_dryrun_mode, nosync=nosync,
+                                            ldap_backend_forced_uri=ldap_backend_forced_uri)
     else:
         raise ValueError("Unknown LDAP backend type selected")
 
     else:
         raise ValueError("Unknown LDAP backend type selected")
 
@@ -2235,8 +2272,8 @@ def provision(logger, session_info, smbconf=None,
 
     logger.info("Setting up secrets.ldb")
     secrets_ldb = setup_secretsdb(paths,
 
     logger.info("Setting up secrets.ldb")
     secrets_ldb = setup_secretsdb(paths,
-        session_info=session_info,
-        backend_credentials=provision_backend.credentials, lp=lp)
+                                  session_info=session_info,
+                                  backend_credentials=provision_backend.credentials, lp=lp)
 
     try:
         logger.info("Setting up the registry")
 
     try:
         logger.info("Setting up the registry")
@@ -2274,23 +2311,24 @@ def provision(logger, session_info, smbconf=None,
             adminpass = samba.generate_random_password(12, 32)
             adminpass_generated = True
         else:
             adminpass = samba.generate_random_password(12, 32)
             adminpass_generated = True
         else:
-            adminpass = unicode(adminpass, 'utf-8')
+            if isinstance(adminpass, binary_type):
+                adminpass = adminpass.decode('utf-8')
             adminpass_generated = False
 
         if samdb_fill == FILL_FULL:
             provision_fill(samdb, secrets_ldb, logger, names, paths,
             adminpass_generated = False
 
         if samdb_fill == FILL_FULL:
             provision_fill(samdb, secrets_ldb, logger, names, paths,
-                    schema=schema, targetdir=targetdir, samdb_fill=samdb_fill,
-                    hostip=hostip, hostip6=hostip6,
-                    next_rid=next_rid, dc_rid=dc_rid, adminpass=adminpass,
-                    krbtgtpass=krbtgtpass,
-                    policyguid=policyguid, policyguid_dc=policyguid_dc,
-                    invocationid=invocationid, machinepass=machinepass,
-                    ntdsguid=ntdsguid, dns_backend=dns_backend,
-                    dnspass=dnspass, serverrole=serverrole,
-                    dom_for_fun_level=dom_for_fun_level, am_rodc=am_rodc,
-                    lp=lp, use_ntvfs=use_ntvfs,
-                    skip_sysvolacl=skip_sysvolacl,
-                    backend_store=backend_store)
+                           schema=schema, targetdir=targetdir, samdb_fill=samdb_fill,
+                           hostip=hostip, hostip6=hostip6,
+                           next_rid=next_rid, dc_rid=dc_rid, adminpass=adminpass,
+                           krbtgtpass=krbtgtpass,
+                           policyguid=policyguid, policyguid_dc=policyguid_dc,
+                           invocationid=invocationid, machinepass=machinepass,
+                           ntdsguid=ntdsguid, dns_backend=dns_backend,
+                           dnspass=dnspass, serverrole=serverrole,
+                           dom_for_fun_level=dom_for_fun_level, am_rodc=am_rodc,
+                           lp=lp, use_ntvfs=use_ntvfs,
+                           skip_sysvolacl=skip_sysvolacl,
+                           backend_store=backend_store)
 
         if not is_heimdal_built():
             create_kdc_conf(paths.kdcconf, realm, domain, os.path.dirname(lp.get("log file")))
 
         if not is_heimdal_built():
             create_kdc_conf(paths.kdcconf, realm, domain, os.path.dirname(lp.get("log file")))
@@ -2344,7 +2382,7 @@ def provision(logger, session_info, smbconf=None,
                 os.chmod(paths.binddns_dir, 0o770)
                 os.chown(paths.binddns_dir, -1, paths.bind_gid)
             except OSError:
                 os.chmod(paths.binddns_dir, 0o770)
                 os.chown(paths.binddns_dir, -1, paths.bind_gid)
             except OSError:
-                if not os.environ.has_key('SAMBA_SELFTEST'):
+                if 'SAMBA_SELFTEST' not in os.environ:
                     logger.info("Failed to chown %s to bind gid %u",
                                 paths.binddns_dir, paths.bind_gid)
 
                     logger.info("Failed to chown %s to bind gid %u",
                                 paths.binddns_dir, paths.bind_gid)
 
@@ -2352,7 +2390,7 @@ def provision(logger, session_info, smbconf=None,
                 os.chmod(bind_dns_keytab_path, 0o640)
                 os.chown(bind_dns_keytab_path, -1, paths.bind_gid)
             except OSError:
                 os.chmod(bind_dns_keytab_path, 0o640)
                 os.chown(bind_dns_keytab_path, -1, paths.bind_gid)
             except OSError:
-                if not os.environ.has_key('SAMBA_SELFTEST'):
+                if 'SAMBA_SELFTEST' not in os.environ:
                     logger.info("Failed to chown %s to bind gid %u",
                                 bind_dns_keytab_path, paths.bind_gid)
 
                     logger.info("Failed to chown %s to bind gid %u",
                                 bind_dns_keytab_path, paths.bind_gid)
 
@@ -2377,33 +2415,33 @@ def provision(logger, session_info, smbconf=None,
 
     if use_rfc2307:
         provision_fake_ypserver(logger=logger, samdb=samdb,
 
     if use_rfc2307:
         provision_fake_ypserver(logger=logger, samdb=samdb,
-                domaindn=names.domaindn, netbiosname=names.netbiosname,
-                nisdomain=names.domain.lower(), maxuid=maxuid, maxgid=maxgid)
+                                domaindn=names.domaindn, netbiosname=names.netbiosname,
+                                nisdomain=names.domain.lower(), maxuid=maxuid, maxgid=maxgid)
 
     return result
 
 
 def provision_become_dc(smbconf=None, targetdir=None,
 
     return result
 
 
 def provision_become_dc(smbconf=None, targetdir=None,
-        realm=None, rootdn=None, domaindn=None, schemadn=None, configdn=None,
-        serverdn=None, domain=None, hostname=None, domainsid=None,
-        adminpass=None, krbtgtpass=None, domainguid=None, policyguid=None,
-        policyguid_dc=None, invocationid=None, machinepass=None, dnspass=None,
-        dns_backend=None, root=None, nobody=None, users=None,
-        backup=None, serverrole=None, ldap_backend=None,
-        ldap_backend_type=None, sitename=None, debuglevel=1, use_ntvfs=False):
+                        realm=None, rootdn=None, domaindn=None, schemadn=None, configdn=None,
+                        serverdn=None, domain=None, hostname=None, domainsid=None,
+                        adminpass=None, krbtgtpass=None, domainguid=None, policyguid=None,
+                        policyguid_dc=None, invocationid=None, machinepass=None, dnspass=None,
+                        dns_backend=None, root=None, nobody=None, users=None,
+                        backup=None, serverrole=None, ldap_backend=None,
+                        ldap_backend_type=None, sitename=None, debuglevel=1, use_ntvfs=False):
 
     logger = logging.getLogger("provision")
     samba.set_debug_level(debuglevel)
 
     res = provision(logger, system_session(),
 
     logger = logging.getLogger("provision")
     samba.set_debug_level(debuglevel)
 
     res = provision(logger, system_session(),
-        smbconf=smbconf, targetdir=targetdir, samdb_fill=FILL_DRS,
-        realm=realm, rootdn=rootdn, domaindn=domaindn, schemadn=schemadn,
-        configdn=configdn, serverdn=serverdn, domain=domain,
-        hostname=hostname, hostip=None, domainsid=domainsid,
-        machinepass=machinepass,
-        serverrole="active directory domain controller",
-        sitename=sitename, dns_backend=dns_backend, dnspass=dnspass,
-        use_ntvfs=use_ntvfs)
+                    smbconf=smbconf, targetdir=targetdir, samdb_fill=FILL_DRS,
+                    realm=realm, rootdn=rootdn, domaindn=domaindn, schemadn=schemadn,
+                    configdn=configdn, serverdn=serverdn, domain=domain,
+                    hostname=hostname, hostip=None, domainsid=domainsid,
+                    machinepass=machinepass,
+                    serverrole="active directory domain controller",
+                    sitename=sitename, dns_backend=dns_backend, dnspass=dnspass,
+                    use_ntvfs=use_ntvfs)
     res.lp.set("debuglevel", str(debuglevel))
     return res
 
     res.lp.set("debuglevel", str(debuglevel))
     return res
 
@@ -2420,7 +2458,7 @@ def create_krb5_conf(path, dnsdomain, hostname, realm):
             "DNSDOMAIN": dnsdomain,
             "HOSTNAME": hostname,
             "REALM": realm,
             "DNSDOMAIN": dnsdomain,
             "HOSTNAME": hostname,
             "REALM": realm,
-        })
+    })
 
 
 class ProvisioningError(Exception):
 
 
 class ProvisioningError(Exception):