def restartServer(self): """Restart (service restart) the server, saving the logs and remerging them at the same time""" self.logSaver.backupLog() self.config.logger.info("Restarting server service...") stopResult = Console.sendCommand('net stop "%s"' % self.config.flexServiceName) if stopResult.hasErrors(): self.config.logger.warning("Stop command terminated with errors : %s", stopResult.getErrors()) else: self.config.logger.info("Service stop successful") startResult = Console.sendCommand('net start "%s"' % self.config.flexServiceName) if startResult.hasErrors(): self.config.logger.warning("Restart command terminated with errors : %s", startResult.getErrors()) else: self.config.logger.info("Service start successful") self.logSaver.mergeLastLogs()
def isAlive(self, shost): """Checks whether the server shost is alive shost - address (string) of the server to test Test is done by searching for the feature lines and seeing if total licens issued is greater than 0 """ cmd = self.STAT_COMMAND_TEMPLATE.format(flexPath = self.config.flexPath, host = shost, featureName = self.config.featureName, port = self.config.flexPort) result = Console.sendCommand(cmd) ok = re.compile(r"Users of .*?Total of (\d+) licenses issued.*?Total of (\d+) licenses in use.*") for line in result.getResult().splitlines(): res = ok.match(line) if res is not None: # there is a least one license issued if int(res.group(1)) > 0: return True else: self.config.logger.warning("Status line found but number of issued is not strictly positive : %s", line) return False
def backupLog(self): """Backup the logs to the logSaveDir via copy backup contains the date in the filename Populates the self.lastLogSave variable """ self.logger.info("Saving logs") if not os.path.exists(self.logSaveDir): os.mkdir(self.logSaveDir) if not os.path.exists(self.logFilePath): self.logger.warning("No log file found, nothing to backup") return now = datetime.now().strftime("%Y-%m-%d_%H_%M") filename = "log-%s.log" % now self.lastLogSave = os.path.join(self.logSaveDir, filename) result = Console.sendCommand('copy /Y /B "%s" "%s" ' % (self.logFilePath, self.lastLogSave)) if result.hasErrors(): self.logger.warning("Error during log backup %s", result.getErrors()) else: self.logger.info("Log save as %s" % self.lastLogSave)
def reloadServer(self): """Reload the license server through lmdow and lmreread, use with caution Failsafe : test if server is alive after 1 minute """ self.config.logger.info("Reloading server") for command in self.lmRestartCommands: self.config.logger.debug("Sending command %s", command) if not self.config.mock: result = Console.sendCommand(command) if result.hasErrors(): self.config.logger.warning("Reloading command terminated with errors : %s", result.getErrors()) self.restartServer() break else: self.config.logger.info("Reload command successful : %s", command) time.sleep(60) if not self.isAlive(self.config.currentHost): self.config.logger.warning("Server is not alive, restarting") self.restartServer()
def mergeLastLogs(self): """Merges the lastSaveLog with the current logFile (prepends the last log), maintaining chronology of the logs """ # nothing to merge ! if self.lastLogSave is None: self.logger.warning("No previous saved log to merge") return self.logger.info("Merging logs") # temp filename tempLog = self.logFilePath + "s" # send the copy command result = Console.sendCommand('copy /Y /B "%s" "%s" && copy /Y /B "%s"+"%s" "%s" && del "%s"' % (self.logFilePath, tempLog, self.lastLogSave, tempLog, self.logFilePath, tempLog)) if result.hasErrors(): self.logger.warning("Error while merging logs : %s", result.getErrors()) else: self.logger.info("Logs merged successfully")
def run(self): """Gets and parses the results Dump starts with a date line: Flexible License Manager status on Tue 9/3/2013 09:52 then the feature line with the total: Users of DOORS: (Total of 56 licenses issued; Total of 39 licenses in use) then the user data: parse examples: SBA151 VSDS-BIE-L0240 VSDS-BIE-L0240 (v1.000) (BIE-PVCS-01/19353 212), start Wed 4/12 12:32 SYSTEM bie-pvcs-01 bie-pvcs-01 (v3.000) (BIE-PVCS-01/19353 421), start Wed 4/12 14:53 SBX035 VSDS-BIE-L0150 VSDS-BIE-L0150 (v6.000000) (VSDS-BIE-S002/7587 677), start Wed 4/12 14:58 SBX114 vsds-bie-w0063 bie-pvcs-01 (v8.000) (bie-pvcs-01/27000 1036), start Wed 4/12 12:49 SBX216 vebi7462 bie-pvcs-01 (v8.000) (bie-pvcs-01/27000 826), start Wed 4/12 10:28 rebecca.woodard.ext doorsts VIC-HUD-L017 telelogic (v2009.0602) (bie-pvcs-01/19353 3344), start Mon 3/21 16:37 Surfer rst5 rst5 telelogic (v2009.0602) (bie-pvcs-01/19353 129), start Tue 3/22 9:58 anne-clarissa doorsts VIC-TUA-L0416 telelogic (v2009.0602) (bie-pvcs-01/19353 1334), start Mon 3/21 17:39 """ # Flexible License Manager status on Tue 12/4/2012 07:49 licDatePattern = re.compile(r"\s*{startLine}.+?(\d+/\d+/\d+\s\d+:\d+)\s*".format(startLine = r"Flexible License Manager status on")) totalPattern = re.compile( r"Users of {featureName}.*?Total of (\d+) licenses issued.*?Total of (\d+) licenses in use.*".format(featureName = self._featureName)) userDataPattern = re.compile(r"\s+([\w.-]+)\s+([\w-]+)\s+([\w-]+?)\s+([\w -]*)\(.+\)\s\(.+\), start \w+ (\d+/\d+\s\d+:\d+)\s*") featureLinePattern = re.compile(r"Users of\s.*") while self.isRunning: self._monitorEvent.wait() if not self.isRunning: break dumpLines = Console.sendCommand(self._statusCommand).getSplitResult() if len(dumpLines) <= 0: self.logger.warning("No dump received for %s", self._statusCommand) self._monitorEvent.clear() continue dumpDate = None feature = False relevantLines = [] lineCounter = -1 for singleLine in dumpLines: lineCounter += 1 if not len(singleLine) > 0: continue self.logger.debug(singleLine) # find date of dump generation if dumpDate is None: dateMatch = licDatePattern.match(singleLine) if dateMatch is not None: self.logger.debug("License date matched for line : %s", singleLine) # construct the date dumpDate = datetime.strptime(dateMatch.group(1), "%m/%d/%Y %H:%M") relevantLines.append(lineCounter) continue # end date checking # Users of DOORS: (Total of 56 licenses issued; Total of 14 licenses in use) if dumpDate is not None: # find the beginning of the feature if not feature: fMatch = totalPattern.match(singleLine) if fMatch is not None: feature = True self._serverData.usedLicenses = fMatch.group(2) self._serverData.totalLicenses = fMatch.group(1) relevantLines.append(lineCounter) else: userMatch = userDataPattern.match(singleLine) if userMatch is not None: # add the year found in the dump date because startUsageTimeStr has no year loginDate = datetime.strptime(str(dumpDate.year) + "/" + userMatch.group(5), "%Y/%m/%d %H:%M") self._serverData.addUsage(dumpDate, userMatch.group(1), loginDate, userMatch.group(3), userMatch.group(2)) relevantLines.append(lineCounter) featureLine = featureLinePattern.match(singleLine) if featureLine is not None: feature = False break # end loop dumplines self.logger.info("Total licenses read for host %s : %s/%s", self._serverData.hostname, self._serverData.usedLicenses, self._serverData.totalLicenses) self._serverData.lastDump = dumpDate self._monitorEvent.clear() self.__resultCollected.set() with self._snapshotLock: self._snapshotLogger.info("New dump from %s", self._serverData.hostname) for lineNum in relevantLines: self._snapshotLogger.info(dumpLines[lineNum]) self._snapshotLogger.info("End of dump")