class ApplyPatches: """ Use the constructor to create a threading event that will be used to stop and restart the timer thread when a signal (SIGINT, SIGQUIT) is captured. Additionally, create the timer thread without a message, since it will be set later depending on the type of patches being applied. self.exitStatus is used to inform the caller as to whether or not the program needs to exit, which would be the case if self.exitStatus is not 0. """ def __init__(self): self.timerController = threading.Event() self.timeFeedbackThread = '' self.pid = '' self.exitStatus = 0 self.cancelled = 'no' def applyPatches(self, repositoryList, loggerName): logger = logging.getLogger(loggerName) if len(repositoryList) > 1: logger.info('Applying patches from repositories ' + ', '.join(repositoryList) + '.') else: logger.info('Applying patches from repository ' + repositoryList[0] + '.') logger.info('The patch repository list was determined to be: ' + str(repositoryList)) for repository in repositoryList: time.sleep(2) if 'kernel' in repository.lower(): self.timeFeedbackThread = TimeFeedbackThread(componentMessage='Installing the new kernel', event=self.timerController) self.timeFeedbackThread.start() command = 'zypper -n --non-interactive-include-reboot-patches --no-refresh in -r ' + repository + ' ' + repository + ':*' elif 'additional' not in repository.lower(): self.timeFeedbackThread = TimeFeedbackThread(componentMessage='Applying the OS patches', event=self.timerController) self.timeFeedbackThread.start() command = 'zypper -n --non-interactive-include-reboot-patches --no-refresh up -r ' + repository + ' ' + repository + ':*' result = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, preexec_fn=self.preexec, shell=True) self.pid = result.pid out, err = result.communicate() logger.info('The output of the patch update command (' + command + ') was: ' + out.strip()) if result.returncode == 0: logger.info('Successfully updated the system using patches from the repository ' + repository + '.') else: self.timeFeedbackThread.stopTimer() self.timeFeedbackThread.join() print '' if self.cancelled == 'yes': logger.info('The patch update was cancelled by the user.') print RED + 'The patch update was cancelled; exiting program execution.' + RESETCOLORS else: logger.error('Problems were encountered while updating the system using patches from the repository ' + repository + '.\n' + err) print RED + 'Problems were encountered while applying the patches to the system; check the log file for errors; exiting program execution.' + RESETCOLORS self.exitStatus = 1 return self.timeFeedbackThread.stopTimer() self.timeFeedbackThread.join() print '' if len(repositoryList) > 1: logger.info('Done applying patches from repositories ' + ', '.join(repositoryList) + '.') else: logger.info('Done applying patches from repository ' + repositoryList[0] + '.') def endTask(self): try: self.cancelled = 'yes' pgid = os.getpgid(self.pid) os.killpg(pgid, signal.SIGKILL) except OSError: pass def preexec(self): os.setpgrp() def getExitStatus(self): return self.exitStatus def pauseTimerThread(self): self.timeFeedbackThread.pauseTimer() def resumeTimerThread(self): self.timeFeedbackThread.resumeTimer()
class BuildDeadmanDriver: ''' Use the constructor to create a threading event that will be used to stop and restart the timer thread when a signal (SIGINT, SIGQUIT) is captured. ''' def __init__(self): self.timerController = threading.Event() self.timeFeedbackThread = TimeFeedbackThread(componentMessage = "Rebuilding and installing the deadman driver", event = self.timerController) self.pid = '' self.cancelled = 'no' self.completionStatus = '' #End __init__(self): ''' This function is used to configure the deadman driver on Serviceguard systems. ''' def buildDeadmanDriver(self, loggerName): sgDriverDir = '/opt/cmcluster/drivers' logger = logging.getLogger(loggerName) logger.info("Rebuilding and installing the deadman driver for the new kernel.") #Save the current working directory, so that we can return to it after building the driver. cwd = os.getcwd() try: os.chdir(sgDriverDir) except OSError as err: logger.error("Could not change into the deadman drivers directory (" + sgDriverDir + ").\n" + str(err)) print RED + "Could not change into the deadman drivers directory; check the log file for errors; the deadman driver will have to be manually built/installed." + RESETCOLORS self.completionStatus = 'Failure' return driverBuildCommandsList = ['make modules', 'make modules_install', 'depmod -a'] self.timeFeedbackThread.start() for command in driverBuildCommandsList: buildCommand = command result = subprocess.Popen(buildCommand, stdout=subprocess.PIPE, stderr=subprocess.PIPE, preexec_fn=self.preexec, shell=True) #We get the processes PID in case the process is cancelled and we need to kill the process. self.pid = result.pid out, err = result.communicate() logger.debug("The output of the command (" + command + ") used in building and installing the deadman driver was: " + out.strip()) if result.returncode != 0: self.timeFeedbackThread.stopTimer() self.timeFeedbackThread.join() #Move the cursor to the next line once the timer is stopped. print '' if self.cancelled == 'yes': logger.info("The deadman driver build and install was cancelled by the user.") print RED + "The deadman driver build and install was cancelled; the deadman driver will have to be manually built/installed." + RESETCOLORS else: logger.error("Failed to build and install the deadman driver.\n" + err) print RED + "Failed to build and install the deadman driver; check the log file for errors; the deadman driver will have to be manually built/installed." + RESETCOLORS self.completionStatus = 'Failure' return self.timeFeedbackThread.stopTimer() self.timeFeedbackThread.join() #Move the cursor to the next line once the timer is stopped. print '' try: os.chdir(cwd) except: pass logger.info("Done rebuilding and installing the deadman driver for the new kernel.") self.completionStatus = 'Success' #End buildDeadmanDriver(loggerName): #This function will attempt to kill the running processes as requested by the user. def endTask(self): try: self.cancelled = 'yes' pgid = os.getpgid(self.pid) os.killpg(pgid, signal.SIGKILL) except OSError: pass #End endTask(self): ''' This function is used by subprocess so that signals are not propagated to the child process, which would result in the child process being cancelled without program control. ''' def preexec(self): os.setpgrp() #End preexec(self): #This function is used to get the completion status (Failure or Success) of the deadman build/install. def getCompletionStatus(self): return self.completionStatus #End getExitStatus(self): #This function is used to pause the timer thread when a signal is recieved. def pauseTimerThread(self): self.timeFeedbackThread.pauseTimer() #End pauseTimerThread(self): #This function is used to restart the timer thread once the signal has been handled. def resumeTimerThread(self): self.timeFeedbackThread.resumeTimer()
class ApplyPatches: ''' Use the constructor to create a threading event that will be used to stop and restart the timer thread when a signal (SIGINT, SIGQUIT) is captured. Additionally, create the timer thread without a message, since it will be set later depending on the type of patches being applied. self.exitStatus is used to inform the caller as to whether or not the program needs to exit, which would be the case if self.exitStatus is not 0. ''' def __init__(self): self.timerController = threading.Event() self.timeFeedbackThread = '' self.pid = '' self.exitStatus = 0 self.cancelled = 'no' #End __init__(self): ''' This function is used to apply the patches. ''' def applyPatches(self, repositoryList, loggerName): logger = logging.getLogger(loggerName) if len(repositoryList) > 1: logger.info('Applying patches from repositories ' + ', '.join(repositoryList) + '.') else: logger.info('Applying patches from repository ' + repositoryList[0] + '.') logger.debug("The patch repository list was determined to be: " + str(repositoryList)) #Update OS patches and install kernel patches. for repository in repositoryList: time.sleep(2) if 'kernel' in repository.lower(): self.timeFeedbackThread = TimeFeedbackThread( componentMessage='Installing the new kernel', event=self.timerController) self.timeFeedbackThread.start() command = 'zypper -n --non-interactive-include-reboot-patches in ' + repository + ':*' else: self.timeFeedbackThread = TimeFeedbackThread( componentMessage='Applying the OS patches', event=self.timerController) self.timeFeedbackThread.start() command = 'zypper -n --non-interactive-include-reboot-patches up ' + repository + ':*' result = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, preexec_fn=self.preexec, shell=True) #We get the processes PID in case the process is cancelled and we need to kill the process. self.pid = result.pid out, err = result.communicate() logger.debug("The output of the patch update command (" + command + ") was: " + out.strip()) if result.returncode == 0: logger.info( "Successfully updated the system using patches from the repository " + repository + ".") else: self.timeFeedbackThread.stopTimer() self.timeFeedbackThread.join() #Move the cursor to the next line once the timer is stopped. print '' if self.cancelled == 'yes': logger.info("The patch update was cancelled by the user.") print RED + "The patch update was cancelled; exiting program execution." + RESETCOLORS else: logger.error( "Problems were encountered while updating the system using patches from the repository " + repository + ".\n" + err) print RED + "Problems were encountered while applying the patches to the system; check the log file for errors; exiting program execution." + RESETCOLORS self.exitStatus = 1 return self.timeFeedbackThread.stopTimer() self.timeFeedbackThread.join() #Move the cursor to the next line once the timer is stopped. print '' if len(repositoryList) > 1: logger.info('Done applying patches from repositories ' + ', '.join(repositoryList) + '.') else: logger.info('Done applying patches from repository ' + repositoryList[0] + '.') #End applyPatches(repositoryList, loggerName): #This function will attempt to kill the running processes as requested by the user. def endTask(self): try: self.cancelled = 'yes' pgid = os.getpgid(self.pid) os.killpg(pgid, signal.SIGKILL) except OSError: pass #End endTask(self): ''' This function is used by subprocess so that signals are not propagated to the child process, which would result in the child process being cancelled without program control. ''' def preexec(self): os.setpgrp() #End preexec(self): #This function is used to get the exit status of the patch update. def getExitStatus(self): return self.exitStatus #End getExitStatus(self): #This function is used to pause the timer thread when a signal is recieved. def pauseTimerThread(self): self.timeFeedbackThread.pauseTimer() #End pauseTimerThread(self): #This function is used to restart the timer thread once the signal has been handled. def resumeTimerThread(self): self.timeFeedbackThread.resumeTimer()
class UpdateFusionIO(): """ Use the constructor to create a threading event that will be used to stop and restart the timer thread when a signal (SIGINT, SIGQUIT) is captured. """ def __init__(self): self.timerController = threading.Event() self.timeFeedbackThread = '' self.pid = '' self.cancelled = 'no' self.completionStatus = '' def updateFusionIO(self, patchResourceDict, loggerName, **kwargs): firmwareUpdateRequired = kwargs['firmwareUpdateRequired'] iomemoryCfgBackup = kwargs['iomemory-vslBackup'] logger = logging.getLogger(loggerName) if firmwareUpdateRequired == 'yes': logger.info('Updating the FusionIO firmware and software.') busList = kwargs['busList'].split() else: logger.info('Updating the FusionIO software.') try: patchBaseDir = re.sub( '\\s+', '', patchResourceDict['patchBaseDir']).rstrip('/') fusionIOSubDir = re.sub('\\s+', '', patchResourceDict['fusionIOSubDir']) fusionPatchDir = patchBaseDir + '/' + fusionIOSubDir fusionSourceDir = fusionPatchDir + '/src/' fusionIODriverSrcRPM = re.sub( '\\s+', '', patchResourceDict['fusionIODriverSrcRPM']) except KeyError as err: logger.error('The resource key (' + str(err) + ') was not present in the resource file.') print RED + 'A resource key was not present in the resource file; check the log file for errors; the FusionIO firmware and software/driver will have to be updated manually.' + RESETCOLORS self.completionStatus = 'Failure' return command = 'uname -r' result = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) out, err = result.communicate() logger.debug('The output of the command (' + command + ') used to get the currently used kernel was: ' + out.strip()) if result.returncode != 0: logger.error( "Unable to get the system's current kernel information.\n" + err) print RED + "Unable to get the system's current kernel information; check the log file for errors; the FusionIO firmware and software/driver will have to be updated manually." + RESETCOLORS self.completionStatus = 'Failure' return kernel = out.strip() command = 'uname -p' result = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) out, err = result.communicate() logger.debug('The output of the command (' + command + ") used to get the system's processor type was: " + out.strip()) if result.returncode != 0: logger.error("Unable to get the system's processor type.\n" + err) print RED + "Unable to get the system's processor type; check the log file for errors; the FusionIO firmware and software/driver will have to be updated manually." + RESETCOLORS self.completionStatus = 'Failure' return processorType = out.strip() fusionIODriverRPM = fusionIODriverSrcRPM.replace( 'iomemory-vsl', '-vsl-' + kernel).replace('src', processorType) if firmwareUpdateRequired == 'yes': for bus in busList: time.sleep(2) message = 'Updating ioDIMM in slot ' + bus self.timeFeedbackThread = TimeFeedbackThread( componentMessage=message, event=self.timerController) self.timeFeedbackThread.start() command = 'fio-update-iodrive -y -f -s ' + bus + ' ' + fusionPatchDir + '/' + '*.fff' result = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, preexec_fn=self.preexec, shell=True) self.pid = result.pid out, err = result.communicate() logger.debug('The output of the command (' + command + ') used to update the FusionIO firmware was: ' + out.strip()) self.timeFeedbackThread.stopTimer() self.timeFeedbackThread.join() print '' if result.returncode != 0: if self.cancelled == 'yes': logger.info( 'The FusionIO firmware update was cancelled by the user.' ) print RED + 'The FusionIO firmware update was cancelled; the FusionIO firmware and software/driver will have to be updated manually.' + RESETCOLORS else: logger.error( 'Failed to upgrade the FusionIO firmware:\n' + err) print RED + 'Failed to upgrade the FusionIO firmware; check the log file for errors; the FusionIO firmware and software/driver will have to be updated manually.' + RESETCOLORS self.completionStatus = 'Failure' return command = 'rpm -e fio-util' result = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) out, err = result.communicate() logger.debug( 'The output of the command (' + command + ') used to remove the fio-util package before updating the FusionIO software was: ' + out.strip()) if result.returncode != 0: logger.error('Failed to remove the fio-util package:\n' + err) print RED + 'Failed to remove the fio-util package; check the log file for errors; the FusionIO software/driver will have to be updated manually.' + RESETCOLORS self.completionStatus = 'Failure' return self.timeFeedbackThread = TimeFeedbackThread( componentMessage='Updating the FusionIO driver and software', event=self.timerController) self.timeFeedbackThread.start() command = 'rpmbuild --rebuild ' + fusionSourceDir + '*.rpm' result = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, preexec_fn=self.preexec, shell=True) self.pid = result.pid out, err = result.communicate() logger.debug('The output of the command (' + command + ') used to build the FusionIO driver was: ' + out.strip()) if result.returncode != 0: self.timeFeedbackThread.stopTimer() self.timeFeedbackThread.join() if self.cancelled == 'yes': logger.info( 'The FusionIO driver and software update was cancelled by the user.' ) print RED + '\nThe FusionIO driver and software update was cancelled; the FusionIO software/driver will have to be updated manually.' + RESETCOLORS else: logger.error('Failed to build the FusionIO driver:\n' + err) print RED + 'Failed to build the FusionIO driver; check the log file for errors; the FusionIO software/driver will have to be updated manually.' + RESETCOLORS self.completionStatus = 'Failure' return out = out.strip() fusionIODriverPattern = re.compile( '.*Wrote:\\s+((/[0-9,a-z,A-Z,_]+)+' + fusionIODriverRPM + ')', re.DOTALL) logger.debug( 'The regex used to get the FusionIO driver RPM location was: ' + fusionIODriverPattern.pattern) driverRPM = re.match(fusionIODriverPattern, out).group(1) logger.debug('The FuionIO driver was determined to be: ' + driverRPM) try: shutil.copy2(driverRPM, fusionPatchDir) except IOError as err: self.timeFeedbackThread.stopTimer() self.timeFeedbackThread.join() print '' logger.error('Unable to retrieve the driver RPM.\n' + err) print RED + 'Unable to retrieve the driver RPM; check log file for errors; the FusionIO firmware and software/driver will have to be updated manually.' + RESETCOLORS self.completionStatus = 'Failure' return command = 'rpm -ivh ' + fusionPatchDir + '/' + '*.rpm' result = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, preexec_fn=self.preexec, shell=True) self.pid = result.pid out, err = result.communicate() logger.debug( 'The output of the command (' + command + ') used to install the FusionIO software and driver was: ' + out.strip()) if result.returncode != 0: self.timeFeedbackThread.stopTimer() self.timeFeedbackThread.join() print '' if self.cancelled == 'yes': logger.info( 'The FusionIO driver and software installation was cancelled by the user.' ) print RED + 'The FusionIO driver and software installation was cancelled; the FusionIO software/driver will have to be installed manually from ' + fusionPatchDir + '.' + RESETCOLORS else: logger.error( 'Failed to install the FusionIO software and driver:\n' + err) print RED + 'Failed to install the FusionIO software and driver; check the log file for errors; the FusionIO software/driver will have to be installed manually from ' + fusionPatchDir + '.' + RESETCOLORS self.completionStatus = 'Failure' return try: shutil.copy2(iomemoryCfgBackup, '/etc/sysconfig/iomemory-vsl') except IOError as err: logger.error( "Failed to restore the system's iomemory-vsl configuration file.\n" + str(err)) print RED + "Failed to restore the system's iomemory-vsl configuration file; check the log file for errors; the file will need to be restored manually." + RESETCOLORS if firmwareUpdateRequired == 'yes': logger.info('Done Updating the FusionIO firmware and software.') else: logger.info('Done Updating the FusionIO software.') self.timeFeedbackThread.stopTimer() self.timeFeedbackThread.join() print '' self.completionStatus = 'Success' def endTask(self): try: self.cancelled = 'yes' pgid = os.getpgid(self.pid) os.killpg(pgid, signal.SIGKILL) except OSError: pass def preexec(self): os.setpgrp() def getCompletionStatus(self): return self.completionStatus def pauseTimerThread(self): self.timeFeedbackThread.pauseTimer() def resumeTimerThread(self): self.timeFeedbackThread.resumeTimer()
class BuildDeadmanDriver: """ Use the constructor to create a threading event that will be used to stop and restart the timer thread when a signal (SIGINT, SIGQUIT) is captured. """ def __init__(self): self.timerController = threading.Event() self.timeFeedbackThread = TimeFeedbackThread( componentMessage='Rebuilding and installing the deadman driver', event=self.timerController) self.pid = '' self.cancelled = 'no' self.completionStatus = '' def buildDeadmanDriver(self, loggerName): sgDriverDir = '/opt/cmcluster/drivers' logger = logging.getLogger(loggerName) logger.info( 'Rebuilding and installing the deadman driver for the new kernel.') cwd = os.getcwd() try: os.chdir(sgDriverDir) except OSError as err: logger.error( 'Could not change into the deadman drivers directory (' + sgDriverDir + ').\n' + str(err)) print RED + 'Could not change into the deadman drivers directory; check the log file for errors; the deadman driver will have to be manually built/installed.' + RESETCOLORS self.completionStatus = 'Failure' return driverBuildCommandsList = [ 'make modules', 'make modules_install', 'depmod -a' ] self.timeFeedbackThread.start() for command in driverBuildCommandsList: buildCommand = command result = subprocess.Popen(buildCommand, stdout=subprocess.PIPE, stderr=subprocess.PIPE, preexec_fn=self.preexec, shell=True) self.pid = result.pid out, err = result.communicate() logger.debug( 'The output of the command (' + command + ') used in building and installing the deadman driver was: ' + out.strip()) if result.returncode != 0: self.timeFeedbackThread.stopTimer() self.timeFeedbackThread.join() print '' if self.cancelled == 'yes': logger.info( 'The deadman driver build and install was cancelled by the user.' ) print RED + 'The deadman driver build and install was cancelled; the deadman driver will have to be manually built/installed.' + RESETCOLORS else: logger.error( 'Failed to build and install the deadman driver.\n' + err) print RED + 'Failed to build and install the deadman driver; check the log file for errors; the deadman driver will have to be manually built/installed.' + RESETCOLORS self.completionStatus = 'Failure' return self.timeFeedbackThread.stopTimer() self.timeFeedbackThread.join() print '' try: os.chdir(cwd) except: pass logger.info( 'Done rebuilding and installing the deadman driver for the new kernel.' ) self.completionStatus = 'Success' def endTask(self): try: self.cancelled = 'yes' pgid = os.getpgid(self.pid) os.killpg(pgid, signal.SIGKILL) except OSError: pass def preexec(self): os.setpgrp() def getCompletionStatus(self): return self.completionStatus def pauseTimerThread(self): self.timeFeedbackThread.pauseTimer() def resumeTimerThread(self): self.timeFeedbackThread.resumeTimer()