[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