diff options
-rw-r--r-- | source4/scripting/python/samba/provision.py | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/source4/scripting/python/samba/provision.py b/source4/scripting/python/samba/provision.py index ec8dc100ef..c46c290ae1 100644 --- a/source4/scripting/python/samba/provision.py +++ b/source4/scripting/python/samba/provision.py @@ -27,6 +27,7 @@ from base64 import b64encode import os +import re import pwd import grp import logging @@ -153,6 +154,7 @@ def get_domain_descriptor(domain_sid): return ndr_pack(sec) DEFAULTSITE = "Default-First-Site-Name" +LAST_PROVISION_USN_ATTRIBUTE = "lastProvisionUSN" class ProvisionPaths(object): @@ -189,7 +191,94 @@ class ProvisionNames(object): self.hostname = None self.sitename = None self.smbconf = None + +def updateProvisionUSN(samdb, low, high, replace = 0): + """Update the field provisionUSN in sam.ldb + This field is used to track range of USN modified by provision and + upgradeprovision. + This value is used afterward by next provision to figure out if + the field have been modified since last provision. + + :param samdb: An LDB object connect to sam.ldb + :param low: The lowest USN modified by this upgrade + :param high: The highest USN modified by this upgrade + :param replace: A boolean indicating if the range should replace any + existing one or appended (default)""" + + tab = [] + if not replace: + entry = samdb.search(expression="(&(dn=@PROVISION)(%s=*))" % \ + LAST_PROVISION_USN_ATTRIBUTE, base="", + scope=ldb.SCOPE_SUBTREE, + attrs=[LAST_PROVISION_USN_ATTRIBUTE,"dn"]) + for e in entry[0][LAST_PROVISION_USN_ATTRIBUTE]: + tab.append(str(e)) + + tab.append("%s-%s"%(str(low), str(high))) + 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) + samdb.modify(delta) + +def setProvisionUSN(samdb, low, high): + """Set the field provisionUSN in sam.ldb + This field is used to track range of USN modified by provision and + upgradeprovision. + This value is used afterward by next provision to figure out if + the field have been modified since last provision. + + :param samdb: An LDB object connect to sam.ldb + :param low: The lowest USN modified by this upgrade + :param high: The highest USN modified by this upgrade""" + tab = [] + tab.append("%s-%s"%(str(low), str(high))) + 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) + samdb.add(delta) + +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 + :param basedn: A string containing the base DN of 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"]) + return res[0]["uSNChanged"] +def getLastProvisionUSN(sam): + """Get the lastest USN modified by a provision or an upgradeprovision + + :param sam: An LDB object pointing to the sam.ldb + :return an integer corresponding to the highest USN modified by + (upgrade)provision, 0 is this value is unknown""" + + entry = sam.search(expression="(&(dn=@PROVISION)(%s=*))" % \ + LAST_PROVISION_USN_ATTRIBUTE, + base="", scope=ldb.SCOPE_SUBTREE, + attrs=[LAST_PROVISION_USN_ATTRIBUTE]) + if len(entry): + range = [] + idx = 0 + p = re.compile(r'-') + for r in entry[0][LAST_PROVISION_USN_ATTRIBUTE]: + tab = p.split(str(r)) + range.append(tab[0]) + range.append(tab[1]) + idx = idx + 1 + return range + else: + return None class ProvisionResult(object): @@ -1398,6 +1487,13 @@ def provision(setup_dir, logger, session_info, logger.info("A Kerberos configuration suitable for Samba 4 has been " "generated at %s", paths.krb5conf) + lastProvisionUSNs = getLastProvisionUSN(samdb) + maxUSN = get_max_usn(samdb, str(names.rootdn)) + if lastProvisionUSNs != None: + updateProvisionUSN(samdb, 0, maxUSN, 1) + else: + setProvisionUSN(samdb, 0, maxUSN) + if serverrole == "domain controller": create_dns_update_list(lp, logger, paths, setup_path) |