#!/usr/bin/python -ttimport osimport sysimport datetimeimport refrom sets import Setdef get_roles(): hostname = os.popen("/bin/uname -n").readlines()[0].strip() ldap_data = [line.strip() for line in os.popen("/src/bin/modhosts --list %s" % hostname).readlines()] roles = [line.split(":", 1)[1].strip() for line in ldap_data if line.startswith("umnMathDeviceRole:")] return rolesdef yum_groupinstall(packages, excludelist = [], roles = " ".join([item.lower() for item in get_roles()])): print 'Installing packages with groupinstall' regex1 = re.compile('^Error: .+ conflicts with ') excludes = ' '.join(["--exclude=%s" % exclude for exclude in excludelist]) messages = [] (stdin, output) = os.popen4("/usr/bin/yum %s groupinstall %s" % (excludes, roles)) for line in output.readlines():# print line.strip() messages.append(line.strip()) badpkgs = get_excludes(messages) return badpkgsdef yum_listinstall(packages = [], excludelist = []): # Execute yum install on a list of packages and return the output messages = [] (stdin, output) = os.popen4("yum -y %s install %s" % (' '.join(["--exclude=%s" % exclude for exclude in excludelist]), ' '.join(packages))) for line in output.readlines(): messages.append(line.strip()) return messagesdef get_excludes(messages = []): # Convert a list of yum output lines to a list of packages blocking install regex1 = re.compile('^Error: .+ conflicts with ') badpkgs = [] # Parse the lines to generate a list of blocking packages to exclude for message in messages: if message.startswith('Error: Missing Dependency: '): # Missing dependencies badpkgs.append(message.split()[-1]) print "** Block (rule 1): %s" % message.split()[-1] print "** %s" % message elif message.endswith(' is not signed'): # Unsigned packages badpkgs.append(message.split('.', 1)[0].split()[1].rsplit('-', 1)[0]) print "** Block (rule 2): %s" % message.split('.', 1)[0].split()[1].rsplit('-', 1)[0] print "** %s" % message elif regex1.match(message) != None: # Conflicting packages badpkgs.append(message.split()[1]) print "** Block (rule 3): %s" % message.split()[1] print "** %s" % message # Return the list of bad packages return badpkgsdef yum_chunkinstall(packages, excludelist = [], chunksize = 15, maxiterations = 16): print 'Installing packages chunkwise; please be patient' # Break the package list into chunks of packages chunks = [ packages[ (chunksize*chunk):((chunksize*chunk)+chunksize) ] for chunk in range(len(packages)/chunksize) ] # Install each chunk for (chunknumber, chunk) in enumerate(chunks): print "\nInstalling chunk %s of %s" % (chunknumber + 1, len(chunks)) piece = ' '.join(chunk) print "Packages: %s" % piece messages = [] excludes = ' '.join(["--exclude=%s" % exclude for exclude in excludelist]) # Install and capture the output, then inspect the messages for blocking packages print "Excludes: %s" % ' '.join(excludelist) messages = yum_listinstall(chunk, excludelist) badpkgs = get_excludes(messages) iteration = 0 # If no problems, continue with the next chunk if len(badpkgs) == 0: print "OK" while len(badpkgs) > 0: # Otherwise, add badpkgs to the exclude list and try again if iteration == maxiterations: # If we've pruned too many times, give up and move on to the next package excludelist.extend(chunk) excludelist = list(set(excludelist)) print "Too many iterations; giving up chunk" break excludelist.extend(badpkgs) # Remove duplicates excludelist = list(set(excludelist)) # Try to install again messages = yum_listinstall(chunk, excludelist) badpkgs = get_excludes(messages) iteration = iteration + 1 return excludelistdef update_pkgs(chunksize=15): print "Updating software" # Update essential packages precommands = [ ("/usr/bin/yum -y clean metadata","Clearing metadata"), ("/usr/bin/yum -y update yum","Updating yum") ] for command, text in precommands:# print text (stdin, output) = os.popen4(command) for line in output.readlines():# print "%s" % output.strip() pass # If we don't at least look at the output, the next yum process tries to run in parallel and quits exclude_file = open("/etc/adm/package.exclude","r") excludelist = [exclude.strip() for exclude in exclude_file] file_excludelist = [exclude.strip() for exclude in exclude_file] excludes = " ".join(["--exclude=%s" % item for item in excludelist]) roles = " ".join([item.lower() for item in get_roles()]) packages = os.popen("/usr/bin/yum %s -y groupinfo %s" % (excludes, roles)).readlines() packages = [package.strip() for package in packages if package.startswith(" ")] # Try installing packages with yum groupinstall print "Beginning install process" badpkgs = yum_groupinstall(packages, excludelist, roles) if len(badpkgs) == 0: update_log() update_log("All packages installed successfully") else: # If groupinstall fails, install in chunks print "Groupinstall failed!" # Add bad packages found in groupinstall to excludelist excludelist.extend(badpkgs) excludelist = list(set(excludelist)) try: badpkgs = yum_chunkinstall(packages, excludelist) print "Done" update_log() if len(badpkgs) == 0: update_log("All packages installed successfully") else: update_log("Failed packages: %s" % ' '.join(badpkgs)) update_log("%s is not in /etc/adm/package.exclude" % badpkg for badpkg in excludelist if badpkg not in file_excludelist and badpkg in packages) except: print "Installation failed" update_log() update_log("Installation failed")def update_log(message = str(datetime.datetime.now())): log = open("/var/log/mathupdate","a") log.write(message) log.write("\n") log.close()if __name__ == '__main__': update_pkgs()