[patches] upgradeprovision
Matthieu Patou
mat+Informatique.Samba at matws.net
Sun Jan 31 16:03:23 MST 2010
Hi jelmer,
I reattached the patches that tried (and achieved I hope) to take care
of all your remarks.
> 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
>
Ok I'll take your remarks
>> +
>> +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.
>
Well the problem is that provision is printing on the output and it
didn't seems to be easily changeable.
Here are the strings output:
pdc_fsmo_init: no domain object present: (skip loading of domain details)
naming_fsmo_init: no partitions dn present: (skip loading of naming
contexts details)
naming_fsmo_init: no partitions dn present: (skip loading of naming
contexts details)
they are due to this kind of code in dsdb/samdb/ldb_modules/naming_fsmo.c
ldb_debug(ldb, LDB_DEBUG_WARNING,
"naming_fsmo_init: no partitions dn present:
(skip loading of naming contexts details)\n");
So if there is a way to make ldb_debug quiet then I can easily remove
this part.
>
>> +# 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?
>
Yes I checked with simo and andrew B. once on irc it didn't do the job.
See the demo script attached.
>
>> +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
>
> -
>
Matthieu
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: sortdndemo
URL: <http://lists.samba.org/pipermail/samba-technical/attachments/20100201/92005b92/attachment.ksh>
More information about the samba-technical
mailing list