#from modules.createBootloaderConfigFile import configureBootLoader updateTaskStatusDict['configureBootLoader'] = configureBootLoader(loggerName) if (options.a or options.k) and osDistLevel == 'SLES_SP4': print GREEN + 'Phase 4: Updating the patch bundle information file.' + RESETCOLORS else: print GREEN + 'Phase 3: Updating the patch bundle information file.' + RESETCOLORS #from modules.updateReleaseInformation import updateVersionInformationFile if options.a: updateTaskStatusDict['updateVersionInformationFile'] = updateVersionInformationFile(patchResourceDict.copy(), 'all', loggerName) elif options.k: updateTaskStatusDict['updateVersionInformationFile'] = updateVersionInformationFile(patchResourceDict.copy(), 'kernel', loggerName) elif options.o: updateTaskStatusDict['updateVersionInformationFile'] = updateVersionInformationFile(patchResourceDict.copy(), 'os', loggerName) taskFailureList = '' for key, value in updateTaskStatusDict.iteritems(): if value == 'Failure': if taskFailureList == '': taskFailureList += key else: taskFailureList += ', ' + key if taskFailureList == '': if patchResourceDict['postUpdateRequired'] == 'yes': print GREEN + '\nThe system update has completed. Reboot the system for the changes to take affect.\n' + RESETCOLORS print PURPLE + BOLD + UNDERLINE + "Make sure to run the program again with the '-p' option after the system reboots to complete the update procedure!\n" + RESETCOLORS else:
def main(): applicationResourceFile = '/hp/support/patches/resourceFiles/patchResourceFile' loggerName = 'patchLogger' patchResourceDict = init(applicationResourceFile, loggerName) logger = logging.getLogger(loggerName) options = patchResourceDict['options'] if not options.p: print GREEN + 'Phase 2: Updating system with patches.' + RESETCOLORS osDistLevel = patchResourceDict['osDistLevel'] if not options.k: if patchResourceDict['removeRPMs'] or patchResourceDict['addRPMs']: #from modules.oneOffs import OneOffs oneOffs = OneOffs(loggerName) # oneOffs if patchResourceDict['removeRPMs']: if not oneOffs.removeRPMs(patchResourceDict.copy()): print RED + BOLD + '\nProblems were encountered while removing the RPMs which were identified by the patch resource file for removal; check the log file for errors; exiting program execution.' + RESETCOLORS exit(1) if patchResourceDict['addRPMs']: if not oneOffs.addRPMs(patchResourceDict.copy()): print RED + BOLD + '\nProblems were encountered while adding the RPMs which were identified by the patch resource file for addition; check the log file for errors; exiting program execution.' + RESETCOLORS exit(1) original_sigint_handler = signal.getsignal(signal.SIGINT) original_sigquit_handler = signal.getsignal(signal.SIGQUIT) #from modules.applyPatches import ApplyPatches applyPatches = ApplyPatches() # applyPatches s = SignalHandler(applyPatches) signal.signal(signal.SIGINT, s.signal_handler) signal.signal(signal.SIGQUIT, s.signal_handler) workerThread = Thread(target=applyPatches.applyPatches, args=(patchResourceDict['repositoryList'], loggerName)) workerThread.start() while 1: time.sleep(0.1) if not workerThread.is_alive(): if applyPatches.getExitStatus() != 0: exit(1) else: break response = s.getResponse() if response != '': if response == 'y': applyPatches.endTask() exit(1) signal.signal(signal.SIGINT, original_sigint_handler) signal.signal(signal.SIGQUIT, original_sigquit_handler) print '' updateTaskStatusDict = {} if (options.a or options.k) and osDistLevel == 'SLES_SP4': print GREEN + "Phase 3: Updating the system's bootloader." + RESETCOLORS #from modules.createBootloaderConfigFile import configureBootLoader updateTaskStatusDict['configureBootLoader'] = configureBootLoader(loggerName) if (options.a or options.k) and osDistLevel == 'SLES_SP4': print GREEN + 'Phase 4: Updating the patch bundle information file.' + RESETCOLORS else: print GREEN + 'Phase 3: Updating the patch bundle information file.' + RESETCOLORS #from modules.updateReleaseInformation import updateVersionInformationFile if options.a: updateTaskStatusDict['updateVersionInformationFile'] = updateVersionInformationFile(patchResourceDict.copy(), 'all', loggerName)
def main(): if os.geteuid() != 0: print RED + 'You must be root to run this program; exiting program execution.' + RESETCOLORS exit(1) programVersion = '1.4-1' usage = 'usage: %prog [[-h] [-r] [-s] [-u] [-v]]' parser = optparse.OptionParser(usage = usage) parser.add_option('-r', action = 'store_true', default = False, help = 'This option is used to generate a version report.') parser.add_option('-s', action = 'store_true', default = False, help = 'This option is used when upgrading Servicegaurd nodes to indicate which node is the primary node; the secondary node should already be upgraded before envoking this option.') parser.add_option('-u', action = 'store_true', default = False, help = 'This option is used to update the local OS hard drives before the mirror is split.') parser.add_option('-v', action = 'store_true', default = False, help = "This option is used to display the application's version.") (options, args) = parser.parse_args() if options.v: print os.path.basename(sys.argv[0]) + ' ' + programVersion exit(0) if not options.r or options.u: if (options.r or options.s or options.s) and options.u: print RED + "Options 'r', 's', and 'u' are mutually exclusive; please try again; exiting program execution." + RESETCOLORS exit(1) if options.r: versionInformationLogOnly = True else: versionInformationLogOnly = False if options.u: updateOSHarddrives = True else: updateOSHarddrives = False if options.s: command = 'dmidecode -s system-product-name' result = subprocess.Popen(command, stdout = subprocess.PIPE, stderr = subprocess.PIPE, shell = True) (out, err) = result.communicate() out = out.strip() if result.returncode != 0: print RED + "Unable to get the system's model information (dmidecode -s system-product-name); exiting program execution." + RESETCOLORS exit(1) try: systemModel = re.match('[a-z,0-9]+\\s+(.*)', out, re.IGNORECASE).group(1).replace(' ', '') except AttributeError: err = None print RED + "There was a system model match error when trying to match against '" + out + "':\n" + str(err) + '.' + RESETCOLORS exit(1) if systemModel != 'DL380pGen8' and systemModel != 'DL360pGen8': print RED + "The '-s' option can only be used on NFS Serviceguard systems (DL380pGen8 or DL360pGen8)." + RESETCOLORS exit(1) csurBasePath = '/hp/support/csur' currentLogDir = datetime.datetime.now().strftime('Date_%d%H%M%S%b%Y') logBaseDir = csurBasePath + '/log/' + currentLogDir + '/' sessionScreenLog = logBaseDir + 'sessionScreenLog.log' cursesLog = logBaseDir + 'cursesLog.log' try: os.mkdir(logBaseDir) except OSError: err = None print RED + 'Unable to create the current log directory ' + logBaseDir + '; fix the problem and try again; exiting program execution.\n' + str(err) + RESETCOLORS exit(1) try: cursesThread = CursesThread(sessionScreenLog, cursesLog) cursesThread.daemon = True cursesThread.start() initialize = Initialize(cursesThread) csurResourceDict = initialize.init(csurBasePath, logBaseDir, programVersion, versionInformationLogOnly, updateOSHarddrives) if options.s: csurResourceDict['sgNode1'] = True else: csurResourceDict['sgNode1'] = False if options.r: cursesThread.insertMessage([ 'informative', 'The system version report has been created and is in the log directory.']) cursesThread.insertMessage([ 'info', ' ']) if len(csurResourceDict['hardDrivesMissingFirmware']) != 0: cursesThread.insertMessage([ 'warning', 'Hard drive firmware was missing for the following hard drives: ' + csurResourceDict['hardDrivesMissingFirmware'] + '; make sure to file a bug report.']) cursesThread.insertMessage([ 'info', ' ']) elif len(csurResourceDict['componentListDict']['computeNodeList']) == 0 and len(csurResourceDict['hardDrivesMissingFirmware']) != 0: cursesThread.insertMessage([ 'error', "The compute node's local OS hard drives are not being updated, since firmware for the hard drives was missing."]) cursesThread.insertMessage([ 'info', ' ']) cursesThread.insertMessage([ 'error', 'Hard drive firmware was missing for the following hard drives: ' + csurResourceDict['hardDrivesMissingFirmware'] + '; make sure to file a bug report.']) elif len(csurResourceDict['componentListDict']['computeNodeList']) == 0: cursesThread.insertMessage([ 'informative', 'The compute node is already up to date; no action taken.']) else: timerThreadLocation = 1 computeNodeDict = csurResourceDict['componentListDict']['computeNodeList'][0].getComputeNodeDict() hostname = computeNodeDict['hostname'] if updateOSHarddrives: cursesThread.insertMessage([ 'informative', 'Phase 2: Updating compute node ' + hostname + "'s hard drives that need to be updated."]) elif len(csurResourceDict['hardDrivesMissingFirmware']) != 0: cursesThread.insertMessage([ 'warning', 'Phase 2: Updating the compute node ' + hostname + "'s components that need to be updated, however, hard drive firmware was missing for the following hard drives: " + csurResourceDict['hardDrivesMissingFirmware'] + '; make sure to file a bug report.']) else: cursesThread.insertMessage([ 'informative', 'Phase 2: Updating the compute node ' + hostname + "'s components that need to be updated."]) computeNodeUpdate = ComputeNodeUpdate(cursesThread, csurResourceDict.copy(), timerThreadLocation) original_sigint_handler = signal.getsignal(signal.SIGINT) original_sigquit_handler = signal.getsignal(signal.SIGQUIT) s = SignalHandler(cursesThread) signal.signal(signal.SIGINT, s.signal_handler) signal.signal(signal.SIGQUIT, s.signal_handler) workerThread = Thread(target = computeNodeUpdate.updateComputeNodeComponents) workerThread.start() while None: if not workerThread.is_alive(): break response = s.getResponse() if response != '' or response == 'y': computeNodeUpdate.endTask() cursesThread.join() exit(1) signal.signal(signal.SIGINT, original_sigint_handler) signal.signal(signal.SIGQUIT, original_sigquit_handler) componentProblemDict = computeNodeUpdate.getUpdateComponentProblemDict() if not updateOSHarddrives: updateVersionInformationFileResult = updateVersionInformationFile(csurResourceDict.copy()) cursesThread.insertMessage([ 'info', ' ']) if len(componentProblemDict['Software']) == 0 and len(componentProblemDict['Drivers']) == 0 and len(componentProblemDict['Firmware']) == 0: if not updateOSHarddrives: if not updateVersionInformationFileResult: cursesThread.insertMessage([ 'warning', 'The update of compute node ' + hostname + ' completed succesfully, however, the version information file update failed; check the log file for errors and update the file manually.']) cursesThread.insertMessage([ 'info', ' ']) if computeNodeDict['externalStoragePresent']: cursesThread.insertMessage([ 'final', 'Once the version information file is updated, power cycle the attached storage controller(s) and reboot the system for the changes to take effect.']) else: cursesThread.insertMessage([ 'final', 'Once the version information file is updated, reboot the system for the changes to take effect.']) else: cursesThread.insertMessage([ 'informative', 'The update of compute node ' + hostname + ' completed succesfully.']) cursesThread.insertMessage([ 'info', ' ']) if computeNodeDict['externalStoragePresent']: cursesThread.insertMessage([ 'final', 'Power cycle the attached storage controller(s) and reboot the system for the changes to take effect.']) else: cursesThread.insertMessage([ 'final', 'Reboot the system for the changes to take effect.']) else: cursesThread.insertMessage([ 'informative', 'The update of compute node ' + hostname + ' completed succesfully.']) cursesThread.insertMessage([ 'info', ' ']) cursesThread.insertMessage([ 'final', 'Reboot the system for the changes to take effect.']) elif not updateOSHarddrives: errorMessage = 'The following components encountered errors during the update of compute node ' + hostname + '; check the log file for errors:\n' if len(componentProblemDict['Software']) != 0: if 'rpmRemovalFailure' not in componentProblemDict['Software']: errorMessage += 'Software: ' + ', '.join(componentProblemDict['Software'].keys()) + '\n' elif len(componentProblemDict['Software']) == 1: errorMessage += 'Software: ' + componentProblemDict['Software']['rpmRemovalFailure'] + '\n' else: errorMessage += 'Software: ' + componentProblemDict['Software']['rpmRemovalFailure'] + ', ' del componentProblemDict['Software']['rpmRemovalFailure'] errorMessage += ', '.join(componentProblemDict['Software'].keys()) + '\n' if len(componentProblemDict['Drivers']) != 0: errorMessage += 'Drivers: ' + ', '.join(componentProblemDict['Drivers'].keys()) + '\n' if len(componentProblemDict['Firmware']) != 0: errorMessage += 'Firmware: ' + ', '.join(componentProblemDict['Firmware'].keys()) + '\n' if not updateVersionInformationFileResult: errorMessage += 'Also, the version information file update failed; check the log file for errors and update the file manually.' cursesThread.insertMessage([ 'error', errorMessage]) else: cursesThread.insertMessage([ 'error', 'Errors were encountered while updating compute node ' + hostname + "'s hard drive firmware; check the log file for errors."]) cursesThread.insertMessage([ 'info', ' ']) cursesThread.getUserInput([ 'informative', 'Press enter to exit.']) while not cursesThread.isUserInputReady(): time.sleep(0.1) except Exception: cursesThread.join() traceback.print_exc() exit(1) finally: cursesThread.join()
def main(): applicationResourceFile = '/hp/support/patches/resourceFiles/patchResourceFile' loggerName = 'patchLogger' patchResourceDict = init(applicationResourceFile, loggerName) logger = logging.getLogger(loggerName) options = patchResourceDict['options'] if not options.p: print GREEN + 'Phase 2: Updating system with patches.' + RESETCOLORS osDistLevel = patchResourceDict['osDistLevel'] if not options.k: if patchResourceDict['removeRPMs'] or patchResourceDict['addRPMs']: oneOffs = OneOffs(loggerName) if not patchResourceDict['removeRPMs'] and oneOffs.removeRPMs( patchResourceDict.copy()): print RED + BOLD + '\nProblems were encountered while removing the RPMs which were identified by the patch resource file for removal; check the log file for errors; exiting program execution.' + RESETCOLORS exit(1) if patchResourceDict['addRPMs']: if not oneOffs.addRPMs(patchResourceDict.copy()): print RED + BOLD + '\nProblems were encountered while adding the RPMs which were identified by the patch resource file for addition; check the log file for errors; exiting program execution.' + RESETCOLORS exit(1) original_sigint_handler = signal.getsignal(signal.SIGINT) original_sigquit_handler = signal.getsignal(signal.SIGQUIT) applyPatches = ApplyPatches() s = SignalHandler(applyPatches) signal.signal(signal.SIGINT, s.signal_handler) signal.signal(signal.SIGQUIT, s.signal_handler) workerThread = Thread(target=applyPatches.applyPatches, args=(patchResourceDict['repositoryList'], loggerName)) workerThread.start() while None: if not workerThread.is_alive(): if applyPatches.getExitStatus() != 0: exit(1) else: break response = s.getResponse() if response != '' or response == 'y': applyPatches.endTask() exit(1) signal.signal(signal.SIGINT, original_sigint_handler) signal.signal(signal.SIGQUIT, original_sigquit_handler) print '' updateTaskStatusDict = {} if (options.a or options.k) and osDistLevel == 'SLES_SP4': print GREEN + "Phase 3: Updating the system's bootloader." + RESETCOLORS updateTaskStatusDict['configureBootLoader'] = configureBootLoader( loggerName) if (options.a or options.k) and osDistLevel == 'SLES_SP4': print GREEN + 'Phase 4: Updating the patch bundle information file.' + RESETCOLORS else: print GREEN + 'Phase 3: Updating the patch bundle information file.' + RESETCOLORS if options.a: updateTaskStatusDict[ 'updateVersionInformationFile'] = updateVersionInformationFile( patchResourceDict.copy(), 'all', loggerName) elif options.k: updateTaskStatusDict[ 'updateVersionInformationFile'] = updateVersionInformationFile( patchResourceDict.copy(), 'kernel', loggerName) elif options.o: updateTaskStatusDict[ 'updateVersionInformationFile'] = updateVersionInformationFile( patchResourceDict.copy(), 'os', loggerName) taskFailureList = '' for (key, value) in updateTaskStatusDict.iteritems(): if value == 'Failure' or taskFailureList == '': taskFailureList += key else: taskFailureList += ', ' + key if taskFailureList == '': if patchResourceDict['postUpdateRequired'] == 'yes': print GREEN + '\nThe system update has completed. Reboot the system for the changes to take affect.\n' + RESETCOLORS print PURPLE + BOLD + UNDERLINE + "Make sure to run the program again with the '-p' option after the system reboots to complete the update procedure!\n" + RESETCOLORS else: print GREEN + '\nThe system update has successfully completed. Reboot the system for the changes to take affect.\n' + RESETCOLORS elif patchResourceDict['postUpdateRequired'] == 'yes': print RED + BOLD + '\nThe system update failed to complete successfully. Address the failed update tasks (' + taskFailureList + ') and then reboot the system for the changes to take affect.\n' + RESETCOLORS print PURPLE + BOLD + UNDERLINE + "Make sure to run the program again with the '-p' option after the system reboots to complete the update procedure!\n" + RESETCOLORS else: print RED + BOLD + '\nThe system update failed to complete successfully. Address the failed update tasks (' + taskFailureList + ') and then reboot the system for the changes to take affect.\n' + RESETCOLORS try: logBaseDir = re.sub('\\s+', '', patchResourceDict['logBaseDir']).rstrip('/') postUpdateResumeLog = re.sub('\\s+', '', patchResourceDict['postUpdateResumeLog']) postUpdateResumeLog = logBaseDir + '/' + postUpdateResumeLog except KeyError: err = None logger.error('The resource key (' + str(err) + ') was not present in the resource file.') print RED + 'The resource key for the post update resume log was not present in the resource file; check the log file for errors; exiting program execution.' + RESETCOLORS exit(1) resumeDict = {} try: with open(postUpdateResumeLog) as f: for line in f: line = line.strip() if len(line) == 0 and re.match('^\\s*#', line) or re.match( '^\\s+$', line): continue continue line = re.sub('[\'"]', '', line) (key, val) = line.split('=') key = key.strip() resumeDict[key] = val.strip() except IOError: err = None logger.error( 'Unable to get the post update information from resume log.\n' + str(err)) print RED + 'Unable to get the post update information from resume log; check the log file for errors; exiting program execution.' + RESETCOLORS exit(1) count = 2 postUpdateTaskStatusDict = {} if 'isServiceguardSystem' in resumeDict and resumeDict[ 'isServiceguardSystem'] == 'yes': original_sigint_handler = signal.getsignal(signal.SIGINT) original_sigquit_handler = signal.getsignal(signal.SIGQUIT) buildDeadmanDriver = BuildDeadmanDriver() s = SignalHandler(buildDeadmanDriver) signal.signal(signal.SIGINT, s.signal_handler) signal.signal(signal.SIGQUIT, s.signal_handler) print GREEN + 'Phase ' + str( count ) + ': Building and installing the deadman driver.' + RESETCOLORS workerThread = Thread(target=buildDeadmanDriver.buildDeadmanDriver, args=(loggerName, )) workerThread.start() while None: if not workerThread.is_alive(): postUpdateTaskStatusDict[ 'buildDeadmanDriver'] = buildDeadmanDriver.getCompletionStatus( ) break response = s.getResponse() if response != '' or response == 'y': buildDeadmanDriver.endTask() signal.signal(signal.SIGINT, original_sigint_handler) signal.signal(signal.SIGQUIT, original_sigquit_handler) count += 1 if 'isFusionIOSystem' in resumeDict and resumeDict[ 'isFusionIOSystem'] == 'yes': original_sigint_handler = signal.getsignal(signal.SIGINT) original_sigquit_handler = signal.getsignal(signal.SIGQUIT) updateFusionIO = UpdateFusionIO() s = SignalHandler(updateFusionIO) signal.signal(signal.SIGINT, s.signal_handler) signal.signal(signal.SIGQUIT, s.signal_handler) if resumeDict['firmwareUpdateRequired'] == 'yes': print GREEN + 'Phase ' + str( count ) + ': Updating FusionIO firmware, driver, and software.' + RESETCOLORS workerThread = Thread(target=updateFusionIO.updateFusionIO, args=(patchResourceDict.copy(), loggerName), kwargs={ 'firmwareUpdateRequired': resumeDict['firmwareUpdateRequired'], 'busList': resumeDict['busList'], 'iomemory-vslBackup': resumeDict['iomemory-vslBackup'] }) workerThread.start() else: print GREEN + 'Phase ' + str( count ) + ': Updating FusionIO driver and software.' + RESETCOLORS workerThread = Thread(target=updateFusionIO.updateFusionIO, args=(patchResourceDict.copy(), loggerName), kwargs={ 'firmwareUpdateRequired': resumeDict['firmwareUpdateRequired'], 'iomemory-vslBackup': resumeDict['iomemory-vslBackup'] }) workerThread.start() while None: if not workerThread.is_alive(): postUpdateTaskStatusDict[ 'updateFusionIO'] = updateFusionIO.getCompletionStatus() break response = s.getResponse() if response != '' or response == 'y': updateFusionIO.endTask() signal.signal(signal.SIGINT, original_sigint_handler) signal.signal(signal.SIGQUIT, original_sigquit_handler) taskFailureList = '' for (key, value) in postUpdateTaskStatusDict.iteritems(): if value == 'Failure' or taskFailureList == '': taskFailureList += key else: taskFailureList += ', ' + key if taskFailureList == '': print GREEN + '\nThe system update has successfully completed. Reboot the system for the changes to take affect.\n' + RESETCOLORS else: print RED + BOLD + '\nThe system update failed to complete successfully. Address the failed post update tasks (' + taskFailureList + ') and then reboot the system for the changes to take affect.\n' + RESETCOLORS
def main(): if os.geteuid() != 0: print( RED + "You must be root to run this program; exiting program execution." + RESETCOLORS) exit(1) programVersion = '1.2-rc1' #Parse options before setting up curses mode. usage = 'usage: %prog [[-h] [-r] [-u] [-v]]' parser = optparse.OptionParser(usage=usage) parser.add_option('-r', action='store_true', default=False, help='This option is used to generate a version report.') parser.add_option( '-u', action='store_true', default=False, help= 'This option is used to update the local OS hard drives before the mirror is split.' ) parser.add_option( '-v', action='store_true', default=False, help='This option is used to display the application\'s version.') (options, args) = parser.parse_args() if options.v: print(os.path.basename(sys.argv[0]) + ' ' + programVersion) exit(0) count = 0 for option in options: if options[option]: count += 1 if count > 1: print( RED + "Options are mutually exclusive; please try again; exiting program execution." + RESETCOLORS) exit(1) if options.r: versionInformationLogOnly = True else: versionInformationLogOnly = False if options.u: updateOSHarddrives = True else: updateOSHarddrives = False #This is the location of the csur application. csurBasePath = '/hp/support/csur' ''' These log files have their name hardcoded, since their logging starts before the csur application's resource file is read. ''' currentLogDir = datetime.datetime.now().strftime( "Date_%d%b%Y_Time_%H:%M:%S") logBaseDir = csurBasePath + '/log/' + currentLogDir + '/' sessionScreenLog = logBaseDir + 'sessionScreenLog.log' cursesLog = logBaseDir + 'cursesLog.log' try: os.mkdir(logBaseDir) except OSError as err: print(RED + 'Unable to create the current log directory ' + logBaseDir + '; fix the problem and try again; exiting program execution.\n' + str(err) + RESETCOLORS) exit(1) try: ''' The application uses curses to manage the display so that we have two windows. One for feedback and one for conversing. Also, scrolling is implemented. ''' cursesThread = CursesThread(sessionScreenLog, cursesLog) cursesThread.daemon = True cursesThread.start() initialize = Initialize(cursesThread) csurResourceDict = initialize.init(csurBasePath, logBaseDir, programVersion, versionInformationLogOnly, updateOSHarddrives) if options.r: cursesThread.insertMessage([ 'informative', 'The system version report has been created and is in the log directory.' ]) cursesThread.insertMessage(['info', ' ']) else: #The computeNodeList will be empty if the node did not need to be updated. if len(csurResourceDict['componentListDict'] ['computeNodeList']) == 0: cursesThread.insertMessage([ 'informative', 'The compute node is already up to date; no action taken.' ]) else: ''' For a Scale-up system/Compute Nodes only there will only be two timer threads. One for the initial initialization and a second for the update. ''' timerThreadLocation = 1 computeNodeDict = csurResourceDict['componentListDict'][ 'computeNodeList'][0].getComputeNodeDict() hostname = computeNodeDict['hostname'] if updateOSHarddrives: cursesThread.insertMessage([ 'informative', "Phase 2: Updating compute node " + hostname + "'s hard drives that need to be updated." ]) else: cursesThread.insertMessage([ 'informative', "Phase 2: Updating the compute node " + hostname + "'s components that need to be updated." ]) #Instantiate the computeNode update class, which will do the work of updating the compute node. computeNodeUpdate = ComputeNodeUpdate(cursesThread, csurResourceDict.copy(), timerThreadLocation) #Get the current signal handlers so that they can be restored after the update is completed. original_sigint_handler = signal.getsignal(signal.SIGINT) original_sigquit_handler = signal.getsignal(signal.SIGQUIT) ''' Setup signal handler to intercept SIGINT and SIGQUIT. ''' s = SignalHandler(cursesThread) signal.signal(signal.SIGINT, s.signal_handler) signal.signal(signal.SIGQUIT, s.signal_handler) #Create and start the worker thread. workerThread = Thread( target=computeNodeUpdate.updateComputeNodeComponents) workerThread.start() #Wait for the thread to either stop or get interrupted. while 1: time.sleep(0.1) if not workerThread.is_alive(): break ''' The response will be an empty string unless a signal was received. If a signal is received then response is either 'n' (Don't cancel the update) or 'y' (Cancel the update.). ''' response = s.getResponse() if response != '': if response == 'y': computeNodeUpdate.endTask() cursesThread.join() exit(1) #Restore the original signal handlers. signal.signal(signal.SIGINT, original_sigint_handler) signal.signal(signal.SIGQUIT, original_sigquit_handler) componentProblemDict = computeNodeUpdate.getUpdateComponentProblemDict( ) #Update the CSUR version information file. if not updateOSHarddrives: updateVersionInformationFileResult = updateVersionInformationFile( csurResourceDict.copy()) #Move cursor down for formatting purposes. cursesThread.insertMessage(['info', ' ']) if len(componentProblemDict['Software']) == 0 and len( componentProblemDict['Drivers']) == 0 and len( componentProblemDict['Firmware']) == 0: if not updateOSHarddrives: if not updateVersionInformationFileResult: cursesThread.insertMessage([ 'warning', 'The update of compute node ' + hostname + ' completed succesfully, however, the version information file update failed; check the log file for errors and update the file manually.' ]) cursesThread.insertMessage(['info', ' ']) if computeNodeDict['externalStoragePresent']: cursesThread.insertMessage([ 'final', 'Once the version information file is updated, power cycle the attached storage controller(s) and reboot the system for the changes to take effect.' ]) else: cursesThread.insertMessage([ 'final', 'Once the version information file is updated, reboot the system for the changes to take effect.' ]) else: cursesThread.insertMessage([ 'informative', 'The update of compute node ' + hostname + ' completed succesfully.' ]) cursesThread.insertMessage(['info', ' ']) if computeNodeDict['externalStoragePresent']: cursesThread.insertMessage([ 'final', 'Power cycle the attached storage controller(s) and reboot the system for the changes to take effect.' ]) else: cursesThread.insertMessage([ 'final', 'Reboot the system for the changes to take effect.' ]) else: cursesThread.insertMessage([ 'informative', 'The update of compute node ' + hostname + ' completed succesfully.' ]) cursesThread.insertMessage(['info', ' ']) cursesThread.insertMessage([ 'final', 'Reboot the system for the changes to take effect.' ]) else: if not updateOSHarddrives: errorMessage = 'The following components encountered errors during the update of compute node ' + hostname + '; check the log file for errors:\n' if len(componentProblemDict['Software']) != 0: ''' Print the keys which are the names of the software package(s) that had issues while being installed. Else print the names of the software package(s) that had issues while being removed/installed. ''' if not 'rpmRemovalFailure' in componentProblemDict[ 'Software']: errorMessage += 'Software: ' + ', '.join( componentProblemDict['Software'].keys( )) + '\n' else: if len(componentProblemDict['Software']) == 1: errorMessage += 'Software: ' + componentProblemDict[ 'Software']['rpmRemovalFailure'] + '\n' else: errorMessage += 'Software: ' + componentProblemDict[ 'Software']['rpmRemovalFailure'] + ', ' del componentProblemDict['Software'][ 'rpmRemovalFailure'] errorMessage += ', '.join( componentProblemDict['Software'].keys( )) + '\n' if len(componentProblemDict['Drivers']) != 0: errorMessage += 'Drivers: ' + ', '.join( componentProblemDict['Drivers'].keys()) + '\n' if len(componentProblemDict['Firmware']) != 0: errorMessage += 'Firmware: ' + ', '.join( componentProblemDict['Firmware'].keys()) + '\n' if not updateVersionInformationFileResult: errorMessage += 'Also, the version information file update failed; check the log file for errors and update the file manually.' cursesThread.insertMessage(['error', errorMessage]) else: cursesThread.insertMessage([ 'error', "Errors were encountered while updating compute node " + hostname + "'s hard drive firmware; check the log file for errors." ]) cursesThread.insertMessage(['info', ' ']) cursesThread.getUserInput(['informative', 'Press enter to exit.']) while not cursesThread.isUserInputReady(): time.sleep(0.1) except Exception: cursesThread.join() traceback.print_exc() exit(1) finally: cursesThread.join()
def main(): applicationResourceFile = '/hp/support/patches/resourceFiles/patchResourceFile' loggerName = 'patchLogger' patchResourceDict = init(applicationResourceFile, loggerName) logger = logging.getLogger(loggerName) options = patchResourceDict['options'] if not options.p: print GREEN + "Phase 2: Updating system with patches." + RESETCOLORS #Get the current signal handlers so that they can be restored after the patches are installed. original_sigint_handler = signal.getsignal(signal.SIGINT) original_sigquit_handler = signal.getsignal(signal.SIGQUIT) #Instantiate the ApplyPatches class. We will be passing its main function (applyPatches) to a worker thread. applyPatches = ApplyPatches() ''' Setup signal handler to intercept SIGINT and SIGQUIT. Need to pass in a reference to the class object that will be peforming the update. That way we gain access to the TimerThread so that it can be stopped/started. ''' s = SignalHandler(applyPatches) signal.signal(signal.SIGINT, s.signal_handler) signal.signal(signal.SIGQUIT, s.signal_handler) #Create and start the worker thread. workerThread = Thread(target=applyPatches.applyPatches, args=(patchResourceDict['repositoryList'], loggerName,)) workerThread.start() #Wait for the thread to either stop or get interrupted. while 1: time.sleep(0.1) if not workerThread.is_alive(): if applyPatches.getExitStatus() != 0: exit(1) else: break ''' The response will be an empty string unless a signal was received. If a signal is received then response is either 'n' (Don't cancel patch update) or 'y' (Cancel patch update.). ''' response = s.getResponse() if response != '': if response == 'y': applyPatches.endTask() exit(1) signal.signal(signal.SIGINT, original_sigint_handler) signal.signal(signal.SIGQUIT, original_sigquit_handler) ''' Move the cursor down one line for output formatting purposes, so next line does not appear on the same line as the previous line. ''' print '' updateTaskStatusDict = {} #Configure the boot loader for the new kernel if option 'a' or 'k' were selected. if options.a or options.k: print GREEN + "Phase 3: Updating the system's bootloader." + RESETCOLORS updateTaskStatusDict['configureBootLoader'] = configureBootLoader(loggerName) #Update the patch bundler version information file. if options.a or options.k: print GREEN + "Phase 4: Updating the patch bundle information file." + RESETCOLORS else: print GREEN + "Phase 3: Updating the patch bundle information file." + RESETCOLORS if options.a: updateTaskStatusDict['updateVersionInformationFile'] = updateVersionInformationFile(patchResourceDict.copy(), 'all', loggerName) elif options.k: updateTaskStatusDict['updateVersionInformationFile'] = updateVersionInformationFile(patchResourceDict.copy(), 'kernel', loggerName) elif options.o: updateTaskStatusDict['updateVersionInformationFile'] = updateVersionInformationFile(patchResourceDict.copy(), 'os', loggerName) taskFailureList = '' #Now check if any of the update tasks failed and print the appropriate message. for key, value in updateTaskStatusDict.iteritems(): if value == 'Failure': if taskFailureList == '': taskFailureList += key else: taskFailureList += ', ' + key if taskFailureList == '': if patchResourceDict['postUpdateRequired'] == 'yes': print GREEN + "\nThe system update has completed. Reboot the system for the changes to take affect.\n" + RESETCOLORS print PURPLE + BOLD + UNDERLINE + "Make sure to run the program again with the '-p' option after the system reboots to complete the update procedure!\n" + RESETCOLORS else: print GREEN + "\nThe system update has successfully completed. Reboot the system for the changes to take affect.\n" + RESETCOLORS else: if patchResourceDict['postUpdateRequired'] == 'yes': print RED + BOLD + "\nThe system update failed to complete successfully. Address the failed update tasks (" + taskFailureList + ") and then reboot the system for the changes to take affect.\n" + RESETCOLORS print PURPLE + BOLD + UNDERLINE + "Make sure to run the program again with the '-p' option after the system reboots to complete the update procedure!\n" + RESETCOLORS else: print RED + BOLD + "\nThe system update failed to complete successfully. Address the failed update tasks (" + taskFailureList + ") and then reboot the system for the changes to take affect.\n" + RESETCOLORS else: ''' Get the post update resume log, which contains information for the post update tasks. The following is a list of variables currently found in the post update resume log: isServiceguardSystem = 'yes or no' isFusionIOSystem = 'yes or no' firmwareUpdateRequired = 'yes or no' busList = '8c:00.0 8d:00.0 87:00.0 88:00.0' ''' try: logBaseDir = (re.sub('\s+', '', patchResourceDict['logBaseDir'])).rstrip('/') postUpdateResumeLog = re.sub('\s+', '', patchResourceDict['postUpdateResumeLog']) postUpdateResumeLog = logBaseDir + '/' + postUpdateResumeLog except KeyError as err: logger.error("The resource key (" + str(err) + ") was not present in the resource file.") print RED + "The resource key for the post update resume log was not present in the resource file; check the log file for errors; exiting program execution." + RESETCOLORS exit(1) resumeDict = {} try: with open(postUpdateResumeLog) as f: for line in f: line = line.strip() #Ignore commented and blank lines. if len(line) == 0 or re.match("^#", line): continue else: #Remove quotes. line = re.sub('[\'"]', '', line) (key, val) = line.split('=') key = re.sub('\s+', '', key) #Remove space on left before assigning. resumeDict[key] = val.lstrip() except IOError as err: logger.error("Unable to get the post update information from resume log.\n" + str(err)) print RED + "Unable to get the post update information from resume log; check the log file for errors; exiting program execution." + RESETCOLORS exit(1) #This is used for the phase numbering. The count starts at two, since one was already used for the initialization message. count = 2 #This is used to keep track of post update task completion status. postUpdateTaskStatusDict = {} if 'isServiceguardSystem' in resumeDict: if resumeDict['isServiceguardSystem'] == 'yes': #Get the current signal handlers so that they can be restored after the deadman driver is built/installed. original_sigint_handler = signal.getsignal(signal.SIGINT) original_sigquit_handler = signal.getsignal(signal.SIGQUIT) #Instantiate the BuildDeadmanDriver class. We will be passing its main function (buildDeadmanDriver) to a worker thread. buildDeadmanDriver = BuildDeadmanDriver() ''' Setup signal handler to intercept SIGINT and SIGQUIT. Need to pass in a reference to the class object that will be peforming the update. That way we gain access to the TimerThread so that it can be stopped/started. ''' s = SignalHandler(buildDeadmanDriver) signal.signal(signal.SIGINT, s.signal_handler) signal.signal(signal.SIGQUIT, s.signal_handler) #Create and start the worker thread. print GREEN + "Phase " + str(count) + ": Building and installing the deadman driver." + RESETCOLORS workerThread = Thread(target=buildDeadmanDriver.buildDeadmanDriver, args=(loggerName,)) workerThread.start() #Wait for the thread to either stop or get interrupted. while 1: time.sleep(0.1) if not workerThread.is_alive(): postUpdateTaskStatusDict['buildDeadmanDriver'] = buildDeadmanDriver.getCompletionStatus() break ''' The response will be an empty string unless a signal was received. If a signal is received then response is either 'n' (Don't cancel the build/install) or 'y' (Cancel the build/install.). ''' response = s.getResponse() if response != '': if response == 'y': buildDeadmanDriver.endTask() signal.signal(signal.SIGINT, original_sigint_handler) signal.signal(signal.SIGQUIT, original_sigquit_handler) count += 1 if 'isFusionIOSystem' in resumeDict: if resumeDict['isFusionIOSystem'] == 'yes': #Get the current signal handlers so that they can be restored after the FusionIO software and driver are installed. original_sigint_handler = signal.getsignal(signal.SIGINT) original_sigquit_handler = signal.getsignal(signal.SIGQUIT) #Instantiate the UpdateFusionIO class. We will be passing its main function (updateFusionIO) to a worker thread. updateFusionIO = UpdateFusionIO() ''' Setup signal handler to intercept SIGINT and SIGQUIT. Need to pass in a reference to the class object that will be peforming the update. That way we gain access to the TimerThread so that it can be stopped/started. ''' s = SignalHandler(updateFusionIO) signal.signal(signal.SIGINT, s.signal_handler) signal.signal(signal.SIGQUIT, s.signal_handler) #Create and start the worker thread. if resumeDict['firmwareUpdateRequired'] == 'yes': print GREEN + "Phase " + str(count) + ": Updating FusionIO firmware, driver, and software." + RESETCOLORS workerThread = Thread(target=updateFusionIO.updateFusionIO, args=(patchResourceDict.copy(), loggerName,), kwargs={'firmwareUpdateRequired' : resumeDict['firmwareUpdateRequired'], 'busList' : resumeDict['busList']}) workerThread.start() else: print GREEN + "Phase " + str(count) + ": Updating FusionIO driver and software." + RESETCOLORS postUpdateTaskStatusDict['updateFusionIO'] = updateFusionIO(patchResourceDict.copy(), loggerName, firmwareUpdateRequired = resumeDict['firmwareUpdateRequired']) workerThread = Thread(target=updateFusionIO.updateFusionIO, args=(patchResourceDict.copy(), loggerName,), kwargs={'firmwareUpdateRequired' : resumeDict['firmwareUpdateRequired']}) workerThread.start() #Wait for the thread to either stop or get interrupted. while 1: time.sleep(0.1) if not workerThread.is_alive(): postUpdateTaskStatusDict['updateFusionIO'] = updateFusionIO.getCompletionStatus() break ''' The response will be an empty string unless a signal was received. If a signal is received then response is either 'n' (Don't cancel the update) or 'y' (Cancel the update.). ''' response = s.getResponse() if response != '': if response == 'y': updateFusionIO.endTask() signal.signal(signal.SIGINT, original_sigint_handler) signal.signal(signal.SIGQUIT, original_sigquit_handler) taskFailureList = '' for key, value in postUpdateTaskStatusDict.iteritems(): if value == 'Failure': if taskFailureList == '': taskFailureList += key else: taskFailureList += ', ' + key if taskFailureList == '': print GREEN + "\nThe system update has successfully completed. Reboot the system for the changes to take affect.\n" + RESETCOLORS else: print RED + BOLD + "\nThe system update failed to complete successfully. Address the failed post update tasks (" + taskFailureList + ") and then reboot the system for the changes to take affect.\n" + RESETCOLORS
def main(): if os.geteuid() != 0: print( RED + "You must be root to run this program; exiting program execution." + RESETCOLORS) exit(1) programVersion = '1.0-0' #Parse options before setting up curses mode. usage = 'usage: %prog [[-d] [-h] [-v]]' parser = optparse.OptionParser(usage=usage) parser.add_option( '-d', action='store_true', default=False, help= 'This option is used when problems are encountered and additional debug information is needed.' ) parser.add_option( '-v', action='store_true', default=False, help='This option is used to display the application\'s version.') (options, args) = parser.parse_args() if options.v: print(os.path.basename(sys.argv[0]) + ' ' + programVersion) exit(0) if options.d: debug = True else: debug = False #This is the location of the application. csurBasePath = '/hp/support/csur' ''' These log files have their name hardcoded, since their logging starts before the application's resource file is read. ''' logBaseDir = csurBasePath + '/log/' sessionScreenLog = logBaseDir + 'sessionScreenLog.log' cursesLog = logBaseDir + 'cursesLog.log' #Always start with an empty log directory when performing a new update. try: logList = os.listdir(logBaseDir) for log in logList: os.remove(logBaseDir + log) except OSError as err: print(RED + 'Unable to remove old logs in ' + logBaseDir + '; fix the problem and try again; exiting program execution.\n' + str(err) + RESETCOLORS) exit(1) try: ''' The application uses curses to manage the display so that we have two windows. One for feedback and one for conversing. Also, scrolling is implemented. ''' cursesThread = CursesThread(sessionScreenLog, cursesLog) cursesThread.daemon = True cursesThread.start() initialize = Initialize(cursesThread) csurResourceDict = initialize.init(csurBasePath, debug, programVersion) if 'Scale-up' in csurResourceDict['systemType']: #The computeNodeList will be empty if the node did not need to be updated. if len(csurResourceDict['componentListDict'] ['computeNodeList']) == 0: cursesThread.insertMessage([ 'informative', 'The compute node is already up to date; no action taken.' ]) else: ''' For a Scale-up system there will only be two timer threads. One for the initial initialization and a second for the update. ''' timerThreadLocation = 1 computeNodeDict = csurResourceDict['componentListDict'][ 'computeNodeList'][0].getComputeNodeDict() cursesThread.insertMessage([ 'informative', 'Phase 2: Updating the compute node components that need to be updated.' ]) #Instantiate the computeNode update class, which will do the work of updating the compute node. computeNodeUpdate = ComputeNodeUpdate(cursesThread, csurResourceDict.copy(), timerThreadLocation) #Get the current signal handlers so that they can be restored after the update is completed. original_sigint_handler = signal.getsignal(signal.SIGINT) original_sigquit_handler = signal.getsignal(signal.SIGQUIT) ''' Setup signal handler to intercept SIGINT and SIGQUIT. ''' s = SignalHandler(cursesThread) signal.signal(signal.SIGINT, s.signal_handler) signal.signal(signal.SIGQUIT, s.signal_handler) #Create and start the worker thread. workerThread = Thread( target=computeNodeUpdate.updateComputeNodeComponents) workerThread.start() #Wait for the thread to either stop or get interrupted. while 1: time.sleep(0.1) if not workerThread.is_alive(): break ''' The response will be an empty string unless a signal was received. If a signal is received then response is either 'n' (Don't cancel the update) or 'y' (Cancel the update.). ''' response = s.getResponse() if response != '': if response == 'y': computeNodeUpdate.endTask() cursesThread.join() exit(1) #Restore the original signal handlers. signal.signal(signal.SIGINT, original_sigint_handler) signal.signal(signal.SIGQUIT, original_sigquit_handler) componentProblemDict = computeNodeUpdate.getUpdateComponentProblemDict( ) #Update the CSUR version information file. updateVersionInformationFileResult = updateVersionInformationFile( csurResourceDict.copy()) #Move cursor down for formatting purposes. cursesThread.insertMessage(['info', ' ']) if len(componentProblemDict['Software']) == 0 and len( componentProblemDict['Drivers']) == 0 and len( componentProblemDict['Firmware']) == 0: if not updateVersionInformationFileResult: cursesThread.insertMessage([ 'warning', 'The compute node update completed succesfully, however, the version information file update failed; check the log file for errors and update the file manually.' ]) cursesThread.insertMessage(['info', ' ']) if computeNodeDict['externalStoragePresent']: cursesThread.insertMessage([ 'final', 'Once the version information file is updated, power cycle the attached storage controller(s) and reboot the system for the changes to take effect.' ]) else: cursesThread.insertMessage([ 'final', 'Once the version information file is updated, reboot the system for the changes to take effect.' ]) else: cursesThread.insertMessage([ 'informative', 'The compute node update completed succesfully.' ]) cursesThread.insertMessage(['info', ' ']) if computeNodeDict['externalStoragePresent']: cursesThread.insertMessage([ 'final', 'Power cycle the attached storage controller(s) and reboot the system for the changes to take effect.' ]) else: cursesThread.insertMessage([ 'final', 'Reboot the system for the changes to take effect.' ]) else: errorMessage = 'The following components encountered errors during the update; check the log file for errors:\n' if len(componentProblemDict['Software']) != 0: errorMessage += 'Software: ' + ', '.join( componentProblemDict['Software'].keys()) + '\n' if len(componentProblemDict['Drivers']) != 0: errorMessage += 'Drivers: ' + ', '.join( componentProblemDict['Drivers'].keys()) + '\n' if len(componentProblemDict['Firmware']) != 0: errorMessage += 'Firmware: ' + ', '.join( componentProblemDict['Firmware'].keys()) + '\n' if not updateVersionInformationFileResult: errorMessage += 'Also, the version information file update failed; check the log file for errors and update the file manually.' cursesThread.insertMessage(['error', errorMessage]) else: pass cursesThread.insertMessage(['info', ' ']) cursesThread.getUserInput(['informative', 'Press enter to exit.']) while not cursesThread.isUserInputReady(): time.sleep(0.1) except Exception: cursesThread.join() traceback.print_exc() exit(1) finally: cursesThread.join()