class XTerm(QX11EmbedContainer): def __init__(self, parent, xterm_cmd="xterm"): QX11EmbedContainer.__init__(self, parent) self.xterm_cmd = xterm_cmd self.process = QProcess(self) self.connect(self.process, SIGNAL("finished(int, QProcess::ExitStatus)"), self.on_term_close) atexit.register(self.kill) self.show_term() def kill(self): self.process.kill() self.process.waitForFinished() def sizeHint(self): size = QSize(400, 300) return size.expandedTo(QApplication.globalStrut()) def show_term(self): args = [ "-into", str(self.winId()), "-bg", "#000000", # self.palette().color(QPalette.Background).name(), "-fg", "#f0f0f0", # self.palette().color(QPalette.Foreground).name(), # border "-b", "0", "-w", "0", # blink cursor "-bc", '-e', 'tmux', 'new', '-s', 'my_session' ] self.process.start(self.xterm_cmd, args) if self.process.error() == QProcess.FailedToStart: print("xterm not installed") def on_term_close(self, exit_code, exit_status): print("close", exit_code, exit_status) self.close()
def run_process(fused_command, read_output = False): # print "run process", fused_command # qprocess = QProcess() # set_process_env(qprocess) # code_de_retour = qprocess.execute(fused_command) # print "code de retour", code_de_retour # logger.info("command: ") # logger.info(fused_command) # logger.info("code de retour" + str(code_de_retour)) # # # if not qprocess.waitForStarted(): # # # handle a failed command here # # print "qprocess.waitForStarted()" # # return # # # # if not qprocess.waitForReadyRead(): # # # handle a timeout or error here # # print "qprocess.waitForReadyRead()" # # return # # #if not qprocess.waitForFinished(1): # # # qprocess.kill() # # # qprocess.waitForFinished(1) # # # if read_output: # # # logger.info("Erreur") # code_d_erreur = qprocess.error() # dic_err = { 0:"QProcess::FailedToStart", 1:"QProcess::Crashed", 2:"QProcess::TimedOut", 3:"QProcess::WriteError", 4:"QProcess::ReadError", 5:"QProcess::UnknownError" } # logger.info("Code de retour: " + str(code_d_erreur)) # logger.info(dic_err[code_d_erreur]) # # print "get output" # output = str(qprocess.readAllStandardOutput()) # # print "output", output # print 'end output' process = QProcess() process.start(fused_command) if process.waitForStarted(): process.waitForFinished(-1) exit_code = process.exitCode() logger.info("Code de sortie : " + str(exit_code)) if exit_code < 0: code_d_erreur = process.error().data dic_err = { 0:"QProcess::FailedToStart", 1:"QProcess::Crashed", 2:"QProcess::TimedOut", 3:"QProcess::WriteError", 4:"QProcess::ReadError", 5:"QProcess::UnknownError" } logger.info("Code erreur : " + str(code_d_erreur)) logger.info(dic_err[code_d_erreur]) result = process.readAllStandardOutput() # print type(result), result error = process.readAllStandardError().data() # print repr(error) if not error == "\n": logger.info("error : " + "\'" + str(error) + "\'") logger.info("output : " + result.data() + "fin output") return result else: code_d_erreur = process.error() dic_err = { 0:"QProcess::FailedToStart", 1:"QProcess::Crashed", 2:"QProcess::TimedOut", 3:"QProcess::WriteError", 4:"QProcess::ReadError", 5:"QProcess::UnknownError" } logger.info("Code erreur : " + str(code_d_erreur)) logger.info(dic_err[code_d_erreur]) return None
class TerreImageProcess(): def __init__(self): self.process = QProcess() self.process.error[QProcess.ProcessError].connect(self.error_management) self.env = QProcessEnvironment().systemEnvironment() self.set_otb_process_env_default() self.command = "" def run_process(self, command): logger.info(u"Running {}".format(command)) self.process.setProcessEnvironment(self.env) # logger.debug("..............{}".format(self.process.processEnvironment().value("OTB_APPLICATION_PATH"))) # logger.debug("..............{}".format(self.process.processEnvironment().value("PATH"))) # logger.debug("Environ : PATH {}".format(os.environ["PATH"])) # logger.debug("Environ : OTB_APPLICATION_PATH {}".format(os.environ.get("OTB_APPLICATION_PATH", "Empty"))) self.command = command self.process.start(command) if self.process.waitForStarted(): self.process.waitForFinished(-1) exit_code = self.process.exitCode() if exit_code != 0: self.error_management(exit_code) result = self.process.readAllStandardOutput() # logger.debug(" {} {}".format(type(result), result)) error = self.process.readAllStandardError().data() # logger.debug(repr(error)) if not error in ["\n", ""]: logger.error("error : %s"%(error)) output = result.data() logger.info(output) return result else: code_d_erreur = self.process.error() self.error_management(code_d_erreur) return None def error_management(self, errorCode): dic_err = { 0:"QProcess::FailedToStart", 1:"QProcess::Crashed", 2:"QProcess::TimedOut", 3:"QProcess::WriteError", 4:"QProcess::ReadError", 5:"QProcess::UnknownError", 127:"Other, The application may not have been found"} try: type_qt_error = dic_err[errorCode] logger.error(u"Error {} {}".format(errorCode, type_qt_error)) except KeyError: type_qt_error = "" error = self.process.readAllStandardError().data() logger.error(error) logger.error( self.process.readAllStandardOutput()) try: raise terre_image_exceptions.TerreImageRunProcessError(u"Error running : {}\n {}{}".format(self.command, type_qt_error, error )) except UnicodeError: raise terre_image_exceptions.TerreImageRunProcessError(u"Error running : {}\n {}".format(self.command, type_qt_error)) def set_env_var(self, varname, varval, append = False, pre = False): if append == True: if pre == False: # insert value at the end of the variable self.env.insert(varname, self.env.value(varname) + os.pathsep + varval) else: # insert value in head self.env.insert(varname, varval + os.pathsep + self.env.value(varname)) else: # replace value if existing self.env.insert(varname, varval) # logger.debug("env {} {}".format(varname, self.env.value(varname))) def set_otb_process_env(self): dirname = os.path.dirname(os.path.abspath(__file__)) self.set_env_var("OTB_APPLICATION_PATH", os.path.join(dirname, "win32", "plugin"), pre=True) self.set_env_var("PATH", os.path.join(dirname, "win32", "bin"), append = False, pre=True) def set_otb_process_env_custom(self, otb_app_path="", path=""): """ Add the given values to OTB_APPLICATION_PATH and PATH environement variables Args: otb_app_path: path: Returns: """ self.set_env_var("OTB_APPLICATION_PATH", otb_app_path, pre=True) self.set_env_var("PATH", path, append = False, pre=True) def set_otb_process_env_default(self): """ Add the values from the config file to OTB_APPLICATION_PATH and PATH environement variables Args: otb_app_path: path: Returns: """ self.set_env_var("OTB_APPLICATION_PATH", terre_image_configuration.OTB_APPLICATION_PATH, pre=True) self.set_env_var("PATH", terre_image_configuration.PATH, append = True, pre=True) if terre_image_configuration.LD_LIBRARY_PATH: self.set_env_var("LD_LIBRARY_PATH", terre_image_configuration.LD_LIBRARY_PATH, append = True, pre=True)
class TerreImageProcess(): def __init__(self): self.process = QProcess() self.process.error[QProcess.ProcessError].connect( self.error_management) self.env = QProcessEnvironment().systemEnvironment() self.set_otb_process_env_default() self.command = "" def run_process(self, command): logger.info(u"Running {}".format(command)) self.process.setProcessEnvironment(self.env) # logger.debug("..............{}".format(self.process.processEnvironment().value("OTB_APPLICATION_PATH"))) # logger.debug("..............{}".format(self.process.processEnvironment().value("PATH"))) # logger.debug("Environ : PATH {}".format(os.environ["PATH"])) # logger.debug("Environ : OTB_APPLICATION_PATH {}".format(os.environ.get("OTB_APPLICATION_PATH", "Empty"))) self.command = command self.process.start(command) if self.process.waitForStarted(): self.process.waitForFinished(-1) exit_code = self.process.exitCode() if exit_code != 0: self.error_management(exit_code) result = self.process.readAllStandardOutput() # logger.debug(" {} {}".format(type(result), result)) error = self.process.readAllStandardError().data() # logger.debug(repr(error)) if not error in ["\n", ""]: logger.error("error : %s" % (error)) output = result.data() logger.info(output) return result else: code_d_erreur = self.process.error() self.error_management(code_d_erreur) return None def error_management(self, errorCode): dic_err = { 0: "QProcess::FailedToStart", 1: "QProcess::Crashed", 2: "QProcess::TimedOut", 3: "QProcess::WriteError", 4: "QProcess::ReadError", 5: "QProcess::UnknownError", 127: "Other, The application may not have been found" } try: type_qt_error = dic_err[errorCode] logger.error(u"Error {} {}".format(errorCode, type_qt_error)) except KeyError: type_qt_error = "" error = self.process.readAllStandardError().data() logger.error(error) logger.error(self.process.readAllStandardOutput()) try: raise terre_image_exceptions.TerreImageRunProcessError( u"Error running : {}\n {}{}".format(self.command, type_qt_error, error)) except UnicodeError: raise terre_image_exceptions.TerreImageRunProcessError( u"Error running : {}\n {}".format(self.command, type_qt_error)) def set_env_var(self, varname, varval, append=False, pre=False): if append == True: if pre == False: # insert value at the end of the variable self.env.insert(varname, self.env.value(varname) + os.pathsep + varval) else: # insert value in head self.env.insert(varname, varval + os.pathsep + self.env.value(varname)) else: # replace value if existing self.env.insert(varname, varval) # logger.debug("env {} {}".format(varname, self.env.value(varname))) def set_otb_process_env(self): dirname = os.path.dirname(os.path.abspath(__file__)) self.set_env_var("OTB_APPLICATION_PATH", os.path.join(dirname, "win32", "plugin"), pre=True) self.set_env_var("PATH", os.path.join(dirname, "win32", "bin"), append=False, pre=True) def set_otb_process_env_custom(self, otb_app_path="", path=""): """ Add the given values to OTB_APPLICATION_PATH and PATH environement variables Args: otb_app_path: path: Returns: """ self.set_env_var("OTB_APPLICATION_PATH", otb_app_path, pre=True) self.set_env_var("PATH", path, append=False, pre=True) def set_otb_process_env_default(self): """ Add the values from the config file to OTB_APPLICATION_PATH and PATH environement variables Args: otb_app_path: path: Returns: """ self.set_env_var("OTB_APPLICATION_PATH", terre_image_configuration.OTB_APPLICATION_PATH, pre=True) self.set_env_var("PATH", terre_image_configuration.PATH, append=True, pre=True) if terre_image_configuration.LD_LIBRARY_PATH: self.set_env_var("LD_LIBRARY_PATH", terre_image_configuration.LD_LIBRARY_PATH, append=True, pre=True)
class StatsMainWindow(QMainWindow): """ """ LOGDIR = "/s/apps/lin/vfx_test_apps/pulistats/" # SRCDIR = "/datas/jsa/OpenRenderManagement/" BASEDIR = "/s/apps/lin/puli/" reportDict={ "RN usage": { "cmd": BASEDIR + "scripts/util/update_usage_stats", "source":"/s/apps/lin/vfx_test_apps/pulistats/logs/usage_stats.log" }, "Job usage" : { "cmd": BASEDIR + "scripts/util/update_queue_stats", "source":"/s/apps/lin/vfx_test_apps/pulistats/logs/queue_stats.log" }, } queueTrackParam={ "Num errors":"err", "Num jobs":"jobs", "Num paused":"paused", "Num ready or blocked":"ready", "Num rn allocated":"allocatedRN", "Num running":"running", } queueGroupByParam={ "Prod":"prod", "User":"******", "Step":"step", "Type":"type" } def __init__(self): QMainWindow.__init__(self) # Set up the user interface from Designer. self.ui = Ui_MainWindow() self.ui.setupUi(self) self.ui.actionGenerate.setIcon( QIcon( StatsMainWindow.BASEDIR+"tools/statsviewer/rsrc/refresh.png") ) sys.stdout = OutLog( self.ui.log , sys.stdout) xlogger.info("Starting log") # Create tmp file for svg self.svgFile = NamedTemporaryFile( suffix=".svg", delete=True ) xlogger.info("Creating temp file: %s"%self.svgFile.name) # # Set UI values # # Set report choices for key, elem in self.reportDict.items(): self.ui.cbReport.addItem(key) # Set queue param choices for key, elem in sorted(self.queueTrackParam.items()): self.ui.cbTrack.addItem(key) self.ui.cbTrack.setCurrentIndex(1) for key, elem in sorted(self.queueGroupByParam.items()): self.ui.cbGroupBy.addItem(key) self.ui.cbGroupBy.setCurrentIndex(0) # # Connect UI # # Update end date value self.ui.dtEndDate.setDateTime( QDateTime.currentDateTime() ) # Connect up the buttons. self.ui.actionGenerate.triggered.connect(self.generateGraph) self.ui.actionReset.triggered.connect(self.resetParams) self.ui.cbReport.currentIndexChanged.connect( self.updateParamsVisibility ) self.ui.cbReport.currentIndexChanged.connect( self.ui.actionGenerate.trigger ) # Connect Now/Enddate widgets self.ui.chkNow.toggled.connect(lambda toggled: self.ui.dtEndDate.setDateTime( QDateTime.currentDateTime() )) self.ui.chkNow.toggled[bool].connect( self.ui.dtEndDate.setDisabled ) self.ui.chkNow.toggled[bool].connect( self.ui.actionGenerate.trigger ) self.ui.dtEndDate.editingFinished.connect( self.ui.actionGenerate.trigger ) # RN usage params self.ui.chkWorking.toggled.connect( self.ui.actionGenerate.trigger ) self.ui.chkPaused.toggled.connect( self.ui.actionGenerate.trigger ) self.ui.chkOffline.toggled.connect( self.ui.actionGenerate.trigger ) self.ui.chkIdle.toggled.connect( self.ui.actionGenerate.trigger ) # Jobs params self.ui.cbTrack.currentIndexChanged.connect( self.ui.actionGenerate.trigger ) self.ui.cbGroupBy.currentIndexChanged.connect( self.ui.actionGenerate.trigger ) # Handle length slider and spinbox self.ui.slLength.sliderReleased.connect(self.ui.actionGenerate.trigger) self.ui.slLength.valueChanged.connect(self.ui.spLength.setValue) self.ui.spLength.valueChanged.connect(self.ui.slLength.setValue) self.ui.spLength.editingFinished.connect(self.ui.actionGenerate.trigger) self.ui.slLength.sliderReleased.connect(self.ui.actionGenerate.trigger) # Handle display options self.ui.slResolution.sliderReleased.connect(self.ui.actionGenerate.trigger) self.ui.slResolution.valueChanged.connect(self.ui.spResolution.setValue) self.ui.spResolution.valueChanged.connect(self.ui.slResolution.setValue) self.ui.spResolution.editingFinished.connect(self.ui.actionGenerate.trigger) self.ui.cbGraphStyle.currentIndexChanged.connect( self.ui.actionGenerate.trigger ) self.ui.cbGraphType.currentIndexChanged.connect( self.ui.actionGenerate.trigger ) self.ui.cbScaleType.currentIndexChanged.connect( self.ui.actionGenerate.trigger ) self.ui.cbScaleRound.currentIndexChanged.connect( self.ui.actionGenerate.trigger ) self.ui.spScaleResolution.editingFinished.connect(self.ui.actionGenerate.trigger) # Hide/Show report param self.updateParamsVisibility() self.currentCmd = self.reportDict[ str(self.ui.cbReport.currentText()) ]["cmd"] self.currentSource = self.reportDict[ str(self.ui.cbReport.currentText()) ]["source"] xlogger.debug("current command is: %s" % self.currentCmd) xlogger.debug("current source is: %s" % self.currentSource) # self.ui.webView.loadFinished.connect( self.initSvgFile ) # self.ui.webView.settings().setAttribute( QWebSettings.JavascriptEnabled, True) # self.ui.webView.load(QUrl("rsrc/www/display.html")) self.ui.webView.load(QUrl(self.svgFile.name)) self.generateGraph() # self.ui.webView.load(QUrl("/tmp/graph.svg")) # self.ui.webView.load(QUrl("/tmp/test.html")) # def initSvgFile(self): # doc = self.ui.webView.page().mainFrame().documentElement() # em = doc.findFirst("embed") # em.setAttribute("src", self.svgFile.name) # print "RESULT=%r" % self.ui.webView.page().mainFrame().toHtml() # self.ui.webView.show() # pass def updateParamsVisibility(self): if self.ui.cbReport.currentText() == "RN usage": self.ui.gbJobUsage.setVisible( False ) self.ui.gbRnUsage.setVisible( True ) else: self.ui.gbJobUsage.setVisible( True ) self.ui.gbRnUsage.setVisible( False ) def closeEvent(self, pEvent): """ """ xlogger.info("Removing temp file: %s"%self.svgFile.name) del(self.svgFile) pEvent.accept() def createBaseArgs(self): """ """ startDate = self.ui.dtEndDate.dateTime().addSecs( -1*self.ui.slLength.value()*3600 ) endDate = self.ui.dtEndDate.dateTime() title = "%s - %s" % (startDate.toString("MM/dd hh:mm"), endDate.toString("MM/dd hh:mm")) startTime = startDate.toTime_t() endTime = endDate.toTime_t() args = [] args += ["-t", title] args += ["--startTime", str(startTime)] args += ["--endTime", str(endTime)] args += ["-f", self.currentSource] args += ["-o", self.svgFile.name] args += ["--render-mode", "svg"] args += ["--scale", str(self.ui.spScaleResolution.value())] args += ["--scaleRound", str( int(self.ui.cbScaleRound.currentText()) * 60 )] # # Display params # args += ["--res", str(self.ui.slResolution.value())] args += ["--style", str(self.ui.cbGraphStyle.currentText())] args += ["--width", str(800)] args += ["--height", str(300)] if self.ui.cbGraphType.currentText() == "Stacked": args.append("--stack") if self.ui.cbScaleType.currentText() == "Logarithmic": args.append("--log") return args def createRnUsageArgs(self): """ """ args = [] if not self.ui.chkOffline.isChecked(): args.append("--hide-offline") if not self.ui.chkPaused.isChecked(): args.append("--hide-paused") if not self.ui.chkWorking.isChecked(): args.append("--hide-working") if not self.ui.chkIdle.isChecked(): args.append("--hide-idle") return args def createQueueUsageArgs(self): """ Add 2 fields to graph one value with a specific groupby attribute. Warning: the order of the params are important: groupby, value """ args = [] # args.append("prod") # args.append("jobs") args.append( self.queueGroupByParam[ str(self.ui.cbGroupBy.currentText()) ] ) args.append( self.queueTrackParam[ str(self.ui.cbTrack.currentText()) ] ) xlogger.info( "Tracking %s grouped by %s" % (self.queueTrackParam[ str(self.ui.cbTrack.currentText()) ], self.queueGroupByParam[ str(self.ui.cbGroupBy.currentText()) ]) ) return args def resetParams(self): """ Set default values for all widget elements that might have been changed by user. Signals are blocked for actionGenerate during the reset, a call to grapheGenerate is done to refresh the view at the end. """ xlogger.info( "Reset all params" ) self.ui.actionGenerate.blockSignals(True) self.ui.cbReport.setCurrentIndex(0) self.ui.slLength.setValue(24) self.ui.chkNow.setChecked(True) self.ui.chkWorking.setChecked(True) self.ui.chkPaused.setChecked(True) self.ui.chkIdle.setChecked(True) self.ui.chkOffline.setChecked(True) self.ui.cbTrack.setCurrentIndex(1) self.ui.cbGroupBy.setCurrentIndex(0) self.ui.slResolution.setValue(30) self.ui.cbGraphType.setCurrentIndex(0) self.ui.cbScaleType.setCurrentIndex(0) self.ui.cbGraphStyle.setCurrentIndex(0) self.ui.cbScaleRound.setCurrentIndex(3) self.ui.spScaleResolution.setValue(20) self.ui.actionGenerate.blockSignals(False) self.generateGraph() def generateGraph(self): # # Disable GUI # self.ui.actionGenerate.setEnabled( False ) # # Prepare process params # startDate = self.ui.dtEndDate.dateTime().addSecs( -1*self.ui.slLength.value()*3600 ) endDate = self.ui.dtEndDate.dateTime() self.currentCmd = self.reportDict[ str(self.ui.cbReport.currentText()) ]["cmd"] self.currentSource = self.reportDict[ str(self.ui.cbReport.currentText()) ]["source"] args = self.createBaseArgs() if self.ui.cbReport.currentText() == "RN usage": args += self.createRnUsageArgs() else: args += self.createQueueUsageArgs() # Start thread self.p = QProcess(self) self.p.finished.connect( self.renderFinished ) self.p.started.connect( self.renderStarted ) xlogger.debug("starting command: %s %s" % (self.currentCmd, " ".join(args)) ) res = self.p.start( self.currentCmd, args ) if res==False: xlogger.info("Error starting subprocess: code=%s" % str(self.p.error())) self.ui.statusbar.showMessage("Graph update in progress...", 10000) self.ui.actionGenerate.setEnabled( False ) def renderStarted(self): self.creationStartTime = time.time() QApplication.setOverrideCursor(Qt.WaitCursor) # Activate webview display # self.ui.webView.page().mainFrame().findFirstElement("#wait").setAttribute("class", "visible") # self.ui.webView.page().mainFrame().findFirstElement("#graph").setAttribute("class", "loading") def renderFinished(self, retCode): """ Refresh result in webview """ self.ui.actionGenerate.setEnabled( True ) self.ui.statusbar.clearMessage() QApplication.restoreOverrideCursor() # # Activate webview display # self.ui.webView.page().mainFrame().findFirstElement("#wait").removeAttribute("class") # self.ui.webView.page().mainFrame().findFirstElement("#graph").removeAttribute("class") # svg = self.ui.webView.page().mainFrame().documentElement().findFirst("svg") # svg.setAttribute("style", "opacity: 1.0;") if retCode == 0: # # try to replace svg inline html # result = str(self.p.readAllStandardOutput()) # svg = self.ui.webView.page().mainFrame().findFirstElement("#svg") # svg.setInnerXml(svgMarkup) # svg.replace(svgMarkup) self.ui.webView.reload() xlogger.info("graph updated in %.2fs" % (time.time() - self.creationStartTime )) else: xlogger.info("An error occured")
def run_process(fused_command, read_output=False): # print "run process", fused_command # qprocess = QProcess() # set_process_env(qprocess) # code_de_retour = qprocess.execute(fused_command) # print "code de retour", code_de_retour # logger.info("command: ") # logger.info(fused_command) # logger.info("code de retour" + str(code_de_retour)) # # # if not qprocess.waitForStarted(): # # # handle a failed command here # # print "qprocess.waitForStarted()" # # return # # # # if not qprocess.waitForReadyRead(): # # # handle a timeout or error here # # print "qprocess.waitForReadyRead()" # # return # # #if not qprocess.waitForFinished(1): # # # qprocess.kill() # # # qprocess.waitForFinished(1) # # # if read_output: # # # logger.info("Erreur") # code_d_erreur = qprocess.error() # dic_err = { 0:"QProcess::FailedToStart", 1:"QProcess::Crashed", 2:"QProcess::TimedOut", 3:"QProcess::WriteError", 4:"QProcess::ReadError", 5:"QProcess::UnknownError" } # logger.info("Code de retour: " + str(code_d_erreur)) # logger.info(dic_err[code_d_erreur]) # # print "get output" # output = str(qprocess.readAllStandardOutput()) # # print "output", output # print 'end output' process = QProcess() process.start(fused_command) if process.waitForStarted(): process.waitForFinished(-1) exit_code = process.exitCode() logger.info("Code de sortie : " + str(exit_code)) if exit_code < 0: code_d_erreur = process.error().data dic_err = { 0: "QProcess::FailedToStart", 1: "QProcess::Crashed", 2: "QProcess::TimedOut", 3: "QProcess::WriteError", 4: "QProcess::ReadError", 5: "QProcess::UnknownError" } logger.info("Code erreur : " + str(code_d_erreur)) logger.info(dic_err[code_d_erreur]) result = process.readAllStandardOutput() # print type(result), result error = process.readAllStandardError().data() # print repr(error) if not error == "\n": logger.info("error : " + "\'" + str(error) + "\'") logger.info("output : " + result.data() + "fin output") return result else: code_d_erreur = process.error() dic_err = { 0: "QProcess::FailedToStart", 1: "QProcess::Crashed", 2: "QProcess::TimedOut", 3: "QProcess::WriteError", 4: "QProcess::ReadError", 5: "QProcess::UnknownError" } logger.info("Code erreur : " + str(code_d_erreur)) logger.info(dic_err[code_d_erreur]) return None