[patches] upgradeprovision
Jelmer Vernooij
jelmer at samba.org
Sun Jan 31 14:00:00 MST 2010
Hi Matthieu,
Some initial review comments:
On Sun, Jan 31, 2010 at 11:36:14PM +0300, Matthieu Patou wrote:
> diff --git a/source4/scripting/bin/upgradeprovision b/source4/scripting/bin/upgradeprovision
> index e2ee8d0..2c06007 100755
> --- a/source4/scripting/bin/upgradeprovision
> +++ b/source4/scripting/bin/upgradeprovision
> @@ -30,16 +30,16 @@ import random
> import string
> import re
> import base64
> +from base64 import b64encode
^^^ Please either import what you need from the module or use
MODULE.THING everywhere.
> import tempfile
> # Find right directory when running from source tree
> sys.path.insert(0, "bin/python")
>
> -from base64 import b64encode
>
> import samba
> from samba.credentials import DONT_USE_KERBEROS
> from samba.auth import system_session, admin_session
> -from samba import Ldb, DS_DOMAIN_FUNCTION_2000, DS_DOMAIN_FUNCTION_2003, DS_DOMAIN_FUNCTION_2008, DS_DC_FUNCTION_2008_R2
> +from samba import Ldb
> from ldb import SCOPE_SUBTREE, SCOPE_ONELEVEL, SCOPE_BASE, LdbError
> import ldb
> import samba.getopt as options
> @@ -47,12 +47,13 @@ from samba.samdb import SamDB
> from samba import param
> from samba import glue
> from samba.misc import messageEltFlagToString
> -from samba.provision import ProvisionNames,provision_paths_from_lp,find_setup_dir,FILL_FULL,provision, get_domain_descriptor, get_config_descriptor, secretsdb_self_join
> +from samba.provision import find_setup_dir, get_domain_descriptor, get_config_descriptor, secretsdb_self_join
> from samba.provisionexceptions import ProvisioningError
> from samba.schema import get_dnsyntax_attributes, get_linked_attributes, Schema, get_schema_descriptor
> from samba.dcerpc import misc, security
> from samba.ndr import ndr_pack, ndr_unpack
> from samba.dcerpc.misc import SEC_CHAN_BDC
> +from samba.upgradehelpers import dn_sort,get_paths,newprovision,find_provision_key_parameters,rmall
^^ Please use ", " rather than just ","
> @@ -899,24 +716,27 @@ def update_machine_account_password(paths,creds,session,names):
> else:
> secrets_ldb.transaction_cancel()
>
> +def setup_path(file):
> + return os.path.join(setup_dir, file)
> # From here start the big steps of the program
> # First get files paths
> -paths=get_paths(smbconf=smbconf)
> +paths=get_paths(param,smbconf=smbconf)
^^^ Similarly, please use more space here
> diff --git a/source4/scripting/python/samba/upgradehelpers.py b/source4/scripting/python/samba/upgradehelpers.py
> new file mode 100755
> index 0000000..58da4db
> --- /dev/null
> +++ b/source4/scripting/python/samba/upgradehelpers.py
...
> +import os
> +import sys
> +import string
> +import re
> +# Find right directory when running from source tree
^^^ This comment doesn't seem true anymore
> +
> +import samba
> +from samba import Ldb, DS_DOMAIN_FUNCTION_2000
> +from ldb import SCOPE_SUBTREE, SCOPE_ONELEVEL, SCOPE_BASE, LdbError
> +import ldb
> +from samba.provision import ProvisionNames,provision_paths_from_lp,FILL_FULL,provision
> +from samba.provisionexceptions import ProvisioningError
> +from samba.dcerpc import misc, security
> +from samba.ndr import ndr_pack, ndr_unpack
> +
> +# Get Paths for important objects (ldb, keytabs ...)
> +def get_paths(param,targetdir=None,smbconf=None):
> + if targetdir is not None:
> + if (not os.path.exists(os.path.join(targetdir, "etc"))):
> + os.makedirs(os.path.join(targetdir, "etc"))
> + smbconf = os.path.join(targetdir, "etc", "smb.conf")
> + if smbconf is None:
> + smbconf = param.default_path()
> +
> + if not os.path.exists(smbconf):
> + raise ProvisioningError("Unable to find smb.conf ...")
> +
> + lp = param.LoadParm()
> + lp.load(smbconf)
> + paths = provision_paths_from_lp(lp,lp.get("realm"))
> + return paths
> +
> +
> +# This function guesses (fetches) informations needed to make a fresh provision
> +# from the current provision
> +# It includes: realm, workgroup, partitions, netbiosname, domain guid, ...
> +def find_provision_key_parameters(param,credentials,session_info,paths,smbconf):
> + lp = param.LoadParm()
> + lp.load(paths.smbconf)
> + names = ProvisionNames()
> + # NT domain, kerberos realm, root dn, domain dn, domain dns name
> + names.domain = string.upper(lp.get("workgroup"))
> + names.realm = lp.get("realm")
> + basedn = "DC=" + names.realm.replace(".",",DC=")
> + names.dnsdomain = names.realm
> + names.realm = string.upper(names.realm)
> + # netbiosname
> + secrets_ldb = Ldb(paths.secrets, session_info=session_info, credentials=credentials,lp=lp, options=["modules:samba_secrets"])
> + # Get the netbiosname first (could be obtained from smb.conf in theory)
> + attrs = ["sAMAccountName"]
> + res = secrets_ldb.search(expression="(flatname=%s)"%names.domain,base="CN=Primary Domains", scope=SCOPE_SUBTREE, attrs=attrs)
> + names.netbiosname = str(res[0]["sAMAccountName"]).replace("$","")
> +
> + names.smbconf = smbconf
> + # It's important here to let ldb load with the old module or it's quite
> + # certain that the LDB won't load ...
> + samdb = Ldb(paths.samdb, session_info=session_info,
> + credentials=credentials, lp=lp, options=["modules:samba_dsdb"])
> +
> + # That's a bit simplistic but it's ok as long as we have only 3
> + # partitions
> + attrs2 = ["defaultNamingContext", "schemaNamingContext","configurationNamingContext","rootDomainNamingContext"]
> + current = samdb.search(expression="(objectClass=*)",base="", scope=SCOPE_BASE, attrs=attrs2)
> +
> + names.configdn = current[0]["configurationNamingContext"]
> + configdn = str(names.configdn)
> + names.schemadn = current[0]["schemaNamingContext"]
> + if not (ldb.Dn(samdb, basedn) == (ldb.Dn(samdb, current[0]["defaultNamingContext"][0]))):
> + raise ProvisioningError(("basedn in %s (%s) and from %s (%s) is not the same ..." % (paths.samdb, str(current[0]["defaultNamingContext"][0]), paths.smbconf, basedn)))
> +
> + names.domaindn=current[0]["defaultNamingContext"]
> + names.rootdn=current[0]["rootDomainNamingContext"]
> + # default site name
> + attrs3 = ["cn"]
> + res3= samdb.search(expression="(objectClass=*)",base="CN=Sites,"+configdn, scope=SCOPE_ONELEVEL, attrs=attrs3)
> + names.sitename = str(res3[0]["cn"])
> +
> + # dns hostname and server dn
> + attrs4 = ["dNSHostName"]
> + res4= samdb.search(expression="(CN=%s)"%names.netbiosname,base="OU=Domain Controllers,"+basedn, \
> + scope=SCOPE_ONELEVEL, attrs=attrs4)
> + names.hostname = str(res4[0]["dNSHostName"]).replace("."+names.dnsdomain,"")
> +
> + server_res = samdb.search(expression="serverReference=%s"%res4[0].dn, attrs=[], base=configdn)
> + names.serverdn = server_res[0].dn
> +
> + # invocation id/objectguid
> + res5 = samdb.search(expression="(objectClass=*)",base="CN=NTDS Settings,%s" % str(names.serverdn), scope=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
> + attrs6 = ["objectGUID", "objectSid","msDS-Behavior-Version" ]
> + res6 = samdb.search(expression="(objectClass=*)",base=basedn, scope=SCOPE_BASE, attrs=attrs6)
> + names.domainguid = str(ndr_unpack( misc.GUID,res6[0]["objectGUID"][0]))
> + names.domainsid = ndr_unpack( security.dom_sid,res6[0]["objectSid"][0])
> + if res6[0].get("msDS-Behavior-Version") == None or 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])
> +
> + # policy guid
> + attrs7 = ["cn","displayName"]
> + res7 = samdb.search(expression="(displayName=Default Domain Policy)",base="CN=Policies,CN=System,"+basedn, \
> + scope=SCOPE_ONELEVEL, attrs=attrs7)
> + names.policyid = str(res7[0]["cn"]).replace("{","").replace("}","")
> + # dc policy guid
> + attrs8 = ["cn","displayName"]
> + res8 = samdb.search(expression="(displayName=Default Domain Controllers Policy)",base="CN=Policies,CN=System,"+basedn, \
> + scope=SCOPE_ONELEVEL, attrs=attrs7)
> + if len(res8) == 1:
> + names.policyid_dc = str(res8[0]["cn"]).replace("{","").replace("}","")
> + else:
> + names.policyid_dc = None
> +
> + return names
> +
> +
> +# Create a fresh new reference provision
> +# This provision will be the reference for knowing what has changed in the
> +# since the latest upgrade in the current provision
> +def newprovision(names,setup_dir,creds,session,smbconf,provdir,messagefunc):
> + if os.path.isdir(provdir):
> + rmall(provdir)
> + logstd=os.path.join(provdir,"log.std")
> + os.chdir(os.path.join(setup_dir,".."))
> + os.mkdir(provdir)
> + os.close(2)
> + sys.stderr = open("%s/provision.log"%provdir, "w")
^^^ please don't do this sort of stuff. instead, pass in a function that
can be used for printing debug output or a file handle that should
be used for loggin.
> +# This function sorts two DNs in the lexicographical order and put higher level
> +# DN before.
> +# So given the dns cn=bar,cn=foo and cn=foo the later will be return as smaller
> +# (-1) as it has less level
^^^ You should be able to use sort() with dn's, since we expose
ldb_dn_cmp() at the Python level. Have you tried that?
> +def dn_sort(x,y):
> + p = re.compile(r'(?<!\\),')
> + tab1 = p.split(str(x))
> + tab2 = p.split(str(y))
> + min = 0
> + if (len(tab1) > len(tab2)):
> + min = len(tab2)
> + elif (len(tab1) < len(tab2)):
> + min = len(tab1)
> + else:
> + min = len(tab1)
> + len1=len(tab1)-1
> + len2=len(tab2)-1
> + space = " "
> + # Note: python range go up to upper limit but do not include it
> + for i in range(0,min):
> + ret=cmp(tab1[len1-i],tab2[len2-i])
> + if(ret != 0):
> + return ret
> + else:
> + if(i==min-1):
> + assert len1!=len2,"PB PB PB"+space.join(tab1)+" / "+space.join(tab2)
> + if(len1>len2):
> + return 1
> + else:
> + return -1
> + return ret
> +
Cheers,
Jelmer
-
More information about the samba-technical
mailing list