Exemplo n.º 1
0
    #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:
Exemplo n.º 2
0
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)
Exemplo n.º 3
0
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()
Exemplo n.º 4
0
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
Exemplo n.º 5
0
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()
Exemplo n.º 6
0
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
Exemplo n.º 7
0
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()