From: Matthieu Patou Date: Wed, 25 Nov 2009 13:26:35 +0000 (+0300) Subject: s4: Improve updateprovision X-Git-Tag: samba-4.0.0alpha9~146 X-Git-Url: http://git.samba.org/samba.git/?p=ira%2Fwip.git;a=commitdiff_plain;h=44bc8ac22c402e3d320e080f935636bf26e17500 s4: Improve updateprovision * 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 --- diff --git a/source4/scripting/bin/upgradeprovision b/source4/scripting/bin/upgradeprovision index 054b4734386..74d9829376a 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)