[PATCH 2/2] s4: Improve updateprovision

Matthieu Patou mat at matws.net
Wed Nov 25 06:26:35 MST 2009


  * Define a simple upgrade process mode (module storage change, file name change, copy of new file)
  * Move the schema, configuration and current object upgrade into full upgrade mode
  * Added the --full switch to select the full upgrade mode, and made simple upgrade mode the default
  * Make updateprovision works without any switch (update the provision in the default location)
  * Cleanup the messages
  * Create the reference provision in a subdirectory of the updated provision
---
 source4/scripting/bin/upgradeprovision |   85 +++++++++++++++++++------------
 1 files changed, 52 insertions(+), 33 deletions(-)

diff --git a/source4/scripting/bin/upgradeprovision b/source4/scripting/bin/upgradeprovision
index 8cdee55..b417a71 100755
--- a/source4/scripting/bin/upgradeprovision
+++ b/source4/scripting/bin/upgradeprovision
@@ -53,10 +53,14 @@ replace=2^ldb.FLAG_MOD_REPLACE
 add=2^ldb.FLAG_MOD_ADD
 delete=2^ldb.FLAG_MOD_DELETE
 
-CHANGE = 0x01
-CHANGESD = 0x02
-GUESS = 0x04
-CHANGEALL = 0xff
+#Errors are always logged
+ERROR = 	-1 
+SIMPLE = 	0x00
+CHANGE = 	0x01
+CHANGESD = 	0x02
+GUESS = 	0x04
+PROVISION =	0x08
+CHANGEALL =	0xff
 
 # Attributes that not copied from the reference provision even if they do not exists in the destination object
 # This is most probably because they are populated automatcally when object is created
@@ -82,12 +86,13 @@ def define_what_to_log(opts):
 		what = what | CHANGESD
 	if opts.debugguess:
 		what = what | GUESS
+	if opts.debugprovision:
+		what = what | PROVISION
 	if opts.debugall:
 		what = what | CHANGEALL
 	return what
 
 
-
 parser = optparse.OptionParser("provision [options]")
 sambaopts = options.SambaOptions(parser)
 parser.add_option_group(sambaopts)
@@ -101,6 +106,7 @@ parser.add_option("--debugguess", help="Print information on what is different b
 parser.add_option("--debugchange", help="Print information on what is different but won't be changed", action="store_true")
 parser.add_option("--debugchangesd", help="Print information security descriptors differences", action="store_true")
 parser.add_option("--debugall", help="Print all available information (very verbose)", action="store_true")
+parser.add_option("--full", help="Perform full upgrade of the samdb (schema, configuration, new objects, ...", action="store_true")
 parser.add_option("--targetdir", type="string", metavar="DIR", 
 					help="Set target directory")
 
@@ -115,7 +121,7 @@ def messageprovision(text):
 
 def message(what,text):
 	"""print a message if quiet is not set."""
-	if whatToLog & what:
+	if (whatToLog & what) or (what <= 0 ):
 		print text
 
 if len(sys.argv) == 1:
@@ -146,7 +152,7 @@ def get_paths(targetdir=None,smbconf=None):
 			smbconf = param.default_path()
 
 	if not os.path.exists(smbconf):
-		print >>sys.stderr, "Unable to find smb.conf .."
+		message(ERROR,"Unable to find smb.conf ..")
 		parser.print_usage()
 		sys.exit(1)
 
@@ -179,7 +185,7 @@ def guess_names_from_current_provision(credentials,session_info,paths):
 	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)
+		    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 = ["schemaNamingContext","configurationNamingContext","rootDomainNamingContext"]
@@ -189,7 +195,7 @@ def guess_names_from_current_provision(credentials,session_info,paths):
 	configdn = str(names.configdn)
 	names.schemadn = res2[0]["schemaNamingContext"]
 	if not (rootdn == str(res2[0]["rootDomainNamingContext"])):
-		print >>sys.stderr, "rootdn in sam.ldb and smb.conf is not the same ..."
+		message(ERROR, "rootdn in sam.ldb and smb.conf is not the same ...")
 	else:
 		names.rootdn=res2[0]["rootDomainNamingContext"]
 	# default site name
@@ -234,7 +240,6 @@ def guess_names_from_current_provision(credentials,session_info,paths):
 	# ntds guid
 	attrs9 = ["objectGUID" ]
 	exp = "(dn=CN=NTDS Settings,%s)"%(names.serverdn)
-	print exp
 	res9 = samdb.search(expression="(dn=CN=NTDS Settings,%s)"%(names.serverdn),base=str(names.configdn), scope=SCOPE_SUBTREE, attrs=attrs9)
 	names.ntdsguid = str(ndr_unpack( misc.GUID,res9[0]["objectGUID"][0]))
 
@@ -264,12 +269,18 @@ def print_names(names):
 # 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):
-	random.seed()
-	provdir=os.path.join(os.environ["HOME"],"provision"+str(int(100000*random.random())))
+	message(SIMPLE, "Creating a reference provision")
+	provdir=os.path.join(paths.private_dir,"referenceprovision")
+	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")
+	message(PROVISION, "Reference provision stored in %s"%provdir)
+	message(PROVISION, "STDERR message of provision will be logged in %s/provision.log"%provdir)
+	sys.stderr = open("/dev/stdout", "w")
 	provision(setup_dir, messageprovision,
 		session, creds, smbconf=smbconf, targetdir=provdir,
 		samdb_fill=FILL_FULL, realm=names.realm, domain=names.domain,
@@ -289,7 +300,6 @@ def newprovision(names,setup_dir,creds,session,smbconf):
 		setup_ds_path=None,
 		nosync=None,
 		ldap_dryrun_mode=None)
-	print >>sys.stderr, "provisiondir: "+provdir
 	return provdir
 
 # This function sorts two dn in the lexicographical order and put higher level DN before
@@ -317,7 +327,7 @@ def dn_sort(x,y):
 		else:
 			if(i==min-1):
 				if(len1==len2):
-					print >>sys.stderr,"PB PB PB"+space.join(tab1)+" / "+space.join(tab2)
+					message(ERROR,"PB PB PB"+space.join(tab1)+" / "+space.join(tab2))
 				if(len1>len2):
 					return 1
 				else:
@@ -390,6 +400,7 @@ def handle_special_case(att,delta,new,old,ischema):
 	return 0
 
 def update_secrets(newpaths,paths,creds,session):
+	message(SIMPLE,"update secrets.ldb")
 	newsecrets_ldb = Ldb(newpaths.secrets, session_info=session, credentials=creds,lp=lp)
 	secrets_ldb = Ldb(paths.secrets, session_info=session, credentials=creds,lp=lp, options=["modules:samba_secrets"])
 	res = newsecrets_ldb.search(expression="dn=@MODULES",base="", scope=SCOPE_SUBTREE)
@@ -505,7 +516,7 @@ def check_diff_name(newpaths,paths,creds,session,basedn,names,ischema):
 		sam_ldb.transaction_start()
 
 	empty = ldb.Message()
-	print "There are %d missing objects"%(len(listMissing))
+	message(SIMPLE,"There are %d missing objects"%(len(listMissing)))
 	for dn in listMissing:
 		res = newsam_ldb.search(expression="dn=%s"%(str(dn)),base=basedn, scope=SCOPE_SUBTREE,controls=["search_options:1:2"])
 		delta = sam_ldb.msg_diff(empty,res[0])
@@ -555,7 +566,7 @@ def check_diff_name(newpaths,paths,creds,session,basedn,names,ischema):
 			sam_ldb.modify(delta)
 
 	sam_ldb.transaction_commit()
-	print "There are %d changed objects"%(changed)
+	message(SIMPLE,"There are %d changed objects"%(changed))
 	return hashallSD
 
 
@@ -594,9 +605,9 @@ def update_sds(diffDefSD,diffSD,paths,creds,session,rootdn,domSIDTxt):
 			session = system_session_info
 		descr = security.descriptor.ntsd_from_defaultsd(defSD, domSID,session)
 		if descr.as_sddl(domSID) != oldSD:
-			print "nTSecurity Descriptor for %s do not directly inherit from the defaultSecurityDescriptor and is different from the one of the reference provision, therefor I can't upgrade i"
-			print "Old Descriptor: %s"%(oldSD)
-			print "New Descriptor: %s"%(newSD)
+			message(SIMPLE, "nTSecurity Descriptor for %s do not directly inherit from the defaultSecurityDescriptor and is different from the one of the reference provision, therefor I can't upgrade i")
+			message(SIMPLE,"Old Descriptor: %s"%(oldSD))
+			message(SIMPLE,"New Descriptor: %s"%(newSD))
 			if diffDefSD.has_key(classObj):
 				# We have a pending modification for the defaultSecurityDescriptor of the class Object of the currently inspected object
 				# and we have a conflict so write down that we won't upgrade this defaultSD for this class object
@@ -611,7 +622,7 @@ def update_sds(diffDefSD,diffSD,paths,creds,session,rootdn,domSIDTxt):
         	sam_ldb.modify(delta)
 		
 	sam_ldb.transaction_commit()
-	print "%d nTSecurityDescriptor attribute(s) have been updated"%(upgrade)
+	message(SIMPLE,"%d nTSecurityDescriptor attribute(s) have been updated"%(upgrade))
 	sam_ldb.transaction_start()
 	upgrade = 0
 	for dn in diffDefSD:
@@ -626,7 +637,7 @@ def update_sds(diffDefSD,diffSD,paths,creds,session,rootdn,domSIDTxt):
 			message(CHANGESD,"Not updating the defaultSecurityDescriptor for class object %s as one or more dependant object hasn't been upgraded"%(dn))
 
 	sam_ldb.transaction_commit()
-	print "%d defaultSecurityDescriptor attribute(s) have been updated"%(upgrade)
+	message(SIMPLE,"%d defaultSecurityDescriptor attribute(s) have been updated"%(upgrade))
 			
 def rmall(topdir):
 	for root, dirs, files in os.walk(topdir, topdown=False):
@@ -636,13 +647,12 @@ def rmall(topdir):
 			os.rmdir(os.path.join(root, name))
 	os.rmdir(topdir)
 
-# For each partition check the differences
 
-def check_diff(newpaths,paths,creds,session,names):
-	print "Copy samdb"
+def update_basesamdb(newpaths,paths,names):
+	message(SIMPLE,"Copy samdb")
 	shutil.copy(newpaths.samdb,paths.samdb)
 
-	print "Update ldb names if needed"
+	message(SIMPLE,"Update partitions filename if needed")
 	schemaldb=os.path.join(paths.private_dir,"schema.ldb")
 	configldb=os.path.join(paths.private_dir,"configuration.ldb")
 	usersldb=os.path.join(paths.private_dir,"users.ldb")
@@ -660,16 +670,20 @@ def check_diff(newpaths,paths,creds,session,names):
 	if os.path.isfile(configldb):
 		shutil.copy(configldb,os.path.join(samldbdir,"%s.ldb"%str(names.configdn).upper()))
 		os.remove(configldb)
+
+def update_privilege(newpaths,paths):
+	message(SIMPLE,"Copy privilege")
 	shutil.copy(os.path.join(newpaths.private_dir,"privilege.ldb"),os.path.join(paths.private_dir,"privilege.ldb"))
 
-	print "Doing schema update"
+# For each partition check the differences
+def update_samdb(newpaths,paths,creds,session,names):
+
+	message(SIMPLE, "Doing schema update")
 	hashdef = check_diff_name(newpaths,paths,creds,session,str(names.schemadn),names,1)
-	print "Done with schema update"
-	print "Scanning whole provision for updates and additions"
+	message(SIMPLE,"Done with schema update")
+	message(SIMPLE,"Scanning whole provision for updates and additions")
 	hashSD = check_diff_name(newpaths,paths,creds,session,str(names.rootdn),names,0)
-	print "Done with scanning"
-	print "Updating secrets"
-	update_secrets(newpaths,paths,creds,session)
+	message(SIMPLE,"Done with scanning")
 #	update_sds(hashdef,hashSD,paths,creds,session,str(names.rootdn),names.domainsid)
 
 # From here start the big steps of the program
@@ -689,6 +703,11 @@ provisiondir = newprovision(names,setup_dir,creds,session,smbconf)
 newpaths = get_paths(targetdir=provisiondir)
 populate_backlink(newpaths,creds,session,names.schemadn)
 # Check the difference
-check_diff(newpaths,paths,creds,session,names)
+update_basesamdb(newpaths,paths,names)
+update_secrets(newpaths,paths,creds,session)
+update_privilege(newpaths,paths)
+if opts.full:
+	update_samdb(newpaths,paths,creds,session,names)
+message(SIMPLE,"Upgrade finished !")
 # remove reference provision now that everything is done !
 rmall(provisiondir)
-- 
1.6.3.3


--------------050808020304000504030905--


More information about the samba-technical mailing list