Example #1
0
    def setupGlobals(self):
        #Scene file should be first sys.argv
        try:
            self.scene = sys.argv[1]
            self.scene = self.scene.replace('\\', '/')
        except IndexError:
            self.scene = ""

        #Get the -flag args
        try:
            opts = getopt.getopt(sys.argv[2:], "s:e:n:p:l:x:m:d:c:q:t:")[0]
        except getopt.GetoptError:
            logger.error("Bad Opt!")
            aboutBox(self, "Bad Opt!", "One of the command line options you entered was invalid.\n"+
                "\nPlease remove any unkown opts and try again.")
            sys.exit(2)

        #Defaults
        defName = self.scene.split("/")[-1]
        self.settingsDict = {"-s":101,      #Start Frame (Int)
                            "-e":101,       #End Frame (Int)
                            "-n":defName,   #Nice Name (Str)
                            "-p":"",        #Proj (Str)
                            "-l":"",        #Render Layers (Str,Sep,By,Comma)
                            "-x":"",        #Executabe (Str)
                            "-m":"",        #CMD (Str)
                            "-d":"",        #RenderDirectory (Str)
                            "-c":"",        #Compatabilities (Str,Sep,By,Comma)
                            "-q":"",        #Project Name (Str)
                            "-t":"",        #Job Type (Str)
                            }

        #Apply the -flag args
        optsDict = dict(opts)
        keys = list(optsDict.keys())
        for key in keys:
            self.settingsDict[key] = optsDict[key]
            logger.debug("Setting Key '%s' with opt: '%s'", key, str(optsDict[key]))

        #Fix paths
        self.settingsDict["-p"] = self.settingsDict["-p"].replace('\\', '/')
        #Fix Compatabilities
        self.settingsDict["-c"] = self.settingsDict["-c"].split(",")
        #Add underscores to niceName
        self.settingsDict["-n"] = self.settingsDict["-n"].replace(" ", "_")
        #Move RenderDir to Base CMD
        if self.settingsDict["-d"] != "":
            self.settingsDict["-d"] = self.settingsDict["-d"].replace('\\', '/')
            self.settingsDict["-m"] += " -rd \"{0}\"".format(self.settingsDict["-d"])
Example #2
0
    def __init__(self):
        QMainWindow.__init__(self)
        self.setupUi(self)

        with open(Utils.findResource("styleSheet.css"), "r") as myStyles:
            self.setStyleSheet(myStyles.read())

        self.thisNode = NodeUtils.getThisNodeOBJ()
        self.isVisable = True

        self.pulseThreadStatus = False
        self.renderServerStatus = False
        self.schedThreadStatus = False
        self.autoUpdateStatus = False

        if not self.thisNode:
            self.offlineButton.setEnabled(False)
            self.getoffButton.setEnabled(False)
            logger.error("Node does not exist in database!")
            aboutBox(self, "Error",
                "This node was not found in the database! If you wish to render  "
                "on this node it must be registered with the databse. Run "
                "Register.exe or Register.py to regiester this node and "
                " try again.")
            sys.exit(1)

        self.currentSchedule = self.thisNode.weekSchedule
        self.currentScheduleEnabled = self.thisNode.scheduleEnabled

        self.buildUI()
        self.connectButtons()
        self.updateThisNodeInfo()
        self.startupServers()

        logger.info("Render Node Main is live! Waiting for tasks...")

        try:
            autoHide = True if str(sys.argv[1]).lower() == "true" else False
            logger.info(autoHide)
        except IndexError:
            autoHide = False

        if autoHide and self.trayIconBool:
            logger.info("Autohide is enabled!")
            self.sendToTrayHandler()
        else:
            self.show()
Example #3
0
    def loginButtonHandler(self):
        self.db_username = str(self.user.text())
        self._db_password = str(self.password.text())

        if self.remoteAccess.isChecked():
            #self.host = "REMOTE"
            pass

        try:
            MySQLdb.connect(host=self.host, user=self.db_username,
                            passwd=self._db_password, db=self.databaseName,
                            port=self.port)
            self.loginSuccess = True
            self.close()

        except MySQLdb.Error:
            logger.error("Could not login!")
            aboutBox(self, "Could Not Login",
            "Invalid username/password or server is down...")
Example #4
0
    def buildUI(self):
        def addItem(name, handler, statusTip, menu):
            action = QAction(name, self)
            action.setStatusTip(statusTip)
            action.triggered.connect(handler)
            menu.addAction(action)

        #Add Logging handlers for output field
        emStream = EmittingStream(textWritten=self.normalOutputWritten)
        handler = logging.StreamHandler(emStream)
        handler.setLevel(logging.INFO)
        handler.setFormatter(outputWindowFormatter)
        logger.addHandler(handler)

        sys.stdout = EmittingStream(textWritten=self.normalOutputWritten)
        sys.stderr = EmittingStream(textWritten=self.normalOutputWritten)

        #Get Pixmaps and Icon
        self.donePixmap = QPixmap(Utils.findResource("Images/status/done.png"))
        self.inProgPixmap = QPixmap(Utils.findResource("Images/status/inProgress.png"))
        self.needsAttentionPixmap = QPixmap(Utils.findResource("Images/status/needsAttention.png"))
        self.nonePixmap = QPixmap(Utils.findResource("Images/status/none.png"))
        self.notStartedPixmap = QPixmap(Utils.findResource("Images/status/notStarted.png"))
        self.refreshPixmap = QPixmap(Utils.findResource("Images/refresh.png"))
        self.refreshIcon = QIcon()
        self.refreshIcon.addPixmap(self.refreshPixmap)
        self.RIcon = QIcon(Utils.findResource("Images/RenderNodeMain.png"))

        self.isVisable = True

        self.refreshButton.setIcon(self.refreshIcon)

        self.renderServerPixmap.setPixmap(self.notStartedPixmap)
        self.scheduleThreadPixmap.setPixmap(self.notStartedPixmap)
        self.pulseThreadPixmap.setPixmap(self.notStartedPixmap)
        self.setWindowIcon(self.RIcon)

        #Setup tray icon
        self.trayIcon = QSystemTrayIcon()
        self.trayIconBool = self.trayIcon.isSystemTrayAvailable()
        if self.trayIconBool:
            self.trayIcon.setIcon(self.RIcon)
            self.trayIcon.show()
            self.trayIcon.setVisible(True)
            self.trayIcon.activated.connect(self.activate)
            self.trayIcon.messageClicked.connect(self.activate)

            #Tray Icon Context Menu
            self.taskIconMenu = QMenu(self)

            addItem("Open", self.showWindowHandler,
                    "Show the RenderNodeMain Window", self.taskIconMenu)
            self.taskIconMenu.addSeparator()
            addItem("Update", self.updateThisNodeInfo,
                    "Fetch the latest information from the Database", self.taskIconMenu)
            self.taskIconMenu.addSeparator()
            addItem("Online", self.onlineThisNodeHandler,
                    "Online this node", self.taskIconMenu)
            addItem("Offline", self.offlineThisNodeHandler,
                    "Offline this node", self.taskIconMenu)
            addItem("GetOff!", self.getOffThisNodeHandler,
                    "Kill the current task and offline this node", self.taskIconMenu)

            self.trayIcon.setContextMenu(self.taskIconMenu)
        else:
            logger.error("Tray Icon Error! Could not create tray icon.")
            aboutBox(self, "Tray Icon Error",
                    "Could not create tray icon. Minimizing to tray has been disabled.")
            self.trayButton.setEnabled(False)
Example #5
0
 def aboutBoxHidden(self, title="", msg=""):
     """Creates a window that has been minimzied to the tray"""
     if self.isVisable:
         aboutBox(self, title, msg)
     else:
         self.trayIcon.showMessage(title, msg)
Example #6
0
            hours = int(self.interval / 60 / 60)
            minutes = int(self.interval / 60 % 60)
            logger.info("Scheduler Sleeping for %d hours and %d minutes", hours, minutes)
            self.stopEvent.wait(self.interval)

def pulse():
    host = Utils.myHostName()
    with transaction() as t:
        t.cur.execute("UPDATE hydra_rendernode SET pulse = NOW() "
                    "WHERE host = '{0}'".format(host))

if __name__ == "__main__":
    logger.info("Starting in %s", os.getcwd())
    logger.info("arglist is %s", sys.argv)

    app = QApplication(sys.argv)
    app.quitOnLastWindowClosed = False

    lockFile = InstanceLock("HydraRenderNode")
    lockStatus = lockFile.isLocked()
    logger.debug("Lock File Status: %s", lockStatus)
    if not lockStatus:
        logger.critical("Only one RenderNode is allowed to run at a time! Exiting...")
        aboutBox(None, "ERROR", "Only one RenderNode is allowed to run at a time! Exiting...")
        sys.exit(-1)

    window = RenderNodeMainUI()
    retcode = app.exec_()
    lockFile.remove()
    sys.exit(retcode)
Example #7
0
    def submitButtonHandler(self):

        #######################################################################
        #TODO: Rework this to work with multiple job types
        #######################################################################

        #Getting data in same order as JobTicket
        execName = str(self.executableComboBox.currentText())
        baseCMD = str(self.cmdLineEdit.text())
        startFrame = int(self.startSpinBox.value())
        endFrame = int(self.endSpinBox.value())
        byFrame = int(self.testFramesSpinBox.value())
        taskFile = str(self.sceneLineEdit.text())
        priority = int(self.prioritySpinBox.value())
        phase = 0 #Placeholder, set this later when building the commands
        jobStatus = self.getJobStatus()
        niceName = str(self.niceNameLineEdit.text())
        owner = transaction().db_username
        compatabilityList = self.getReqs()
        maxNodesP1 = int(self.maxNodesP1SpinBox.value())
        maxNodesP2 = int(self.maxNodesP2SpinBox.value())
        timeout = int(self.timeoutSpinbox.value())
        projectName = str(self.projectNameLineEdit.text())
        renderLayers = str(self.renderLayersLineEdit.text()).replace(" ", "")
        jobType = str(self.jobTypeComboBox.currentText())
        proj = str(self.projLineEdit.text())

        #Error Checking
        if len(baseCMD) > 1000:
            aboutBox(self, "baseCMD too long!", "baseCMD must be less than 1000 characters!")
            logger.error("baseCMD too long! baseCMD must be less than 1000 characters!")
            return
        if startFrame > endFrame:
            aboutBox(self, "startFrame is greater than endFrame!", "startFrame must be less than the endFrame!")
            logger.error("startFrame is greater than endFrame!")
            return
        if startFrame > 65535 or endFrame > 65535 or startFrame < 0 or endFrame < 0:
            aboutBox(self, "Frame range out of range!", "Start/End frames must be between 0 and 65535!")
            logger.error("Frame range out of range! Start/End frames must be between 0 and 65535!")
            return
        if byFrame > 255 or byFrame < 0:
            aboutBox(self, "byFrame out of range!", "byFrame must be between 0 and 255!")
            logger.error("byFrame out of range! byFrame must be between 0 and 255!")
            return
        if len(taskFile) > 255 or len(taskFile) < 5:
            aboutBox(self, "taskFile out of range!", "taskFile must be greater than 5 and less than 255 characters")
            logger.error("taskFile out of range! taskFile path must be greater than 5 and less than 255 characters!")
            return
        if priority > 255 or priority < 0:
            aboutBox(self, "Priority out of range!", "Priority must be between 0 and 255!")
            logger.error("Priority out of range! Priority must be between 0 and 255!")
            return
        if len(niceName) > 60 or len(niceName) < 2:
            aboutBox(self, "NiceName out of range!", "NiceName must be more than 1 and less than 60 characters!")
            logger.error("NiceName out of range! NiceName must be more than 1 and less than 60 characters!")
            return
        if len(owner) > 45:
            aboutBox(self, "Owner out of range!", "Owner must be less than 45 characters!")
            logger.error("Owner out of range! Owner must be less than 45 characters!")
            return
        if len(projectName) > 60:
            aboutBox(self, "Project Name out of range!", "Project name must be less than 60 characters!")
            return

        if projectName == "":
            projectName = "UnkownProject"

        if jobType not in ["BatchFile", "FusionComp"]:
            baseCMD += " -proj {0}".format(proj)

        phase01Status = False
        if self.testCheckBox.isChecked():
            logger.info("Building Phase 01")
            #Phase specific overrides
            phase = 1
            #This is cool because at least for now anything with a phase one SHOULD be a Maya Job
            baseCMDOverride = baseCMD + " -x 640 -y 360"

            if ((endFrame - startFrame) % byFrame) != 0:
                phase01FinalFrame = True
                #This looks kinda dumb but works because Python 2.7 divide returns an int
                endFrameOverride = ((((endFrame - startFrame) / byFrame) * byFrame) + startFrame)
            else:
                phase01FinalFrame = False
                endFrameOverride = endFrame

            phase01 = submitJob(niceName, projectName, owner, jobStatus,
                                compatabilityList, execName, baseCMDOverride,
                                startFrame, endFrameOverride, byFrame, renderLayers,
                                taskFile, int(priority * 1.25), phase, maxNodesP1,
                                timeout, 10, jobType)

            logger.info("Phase 01 submitted with id: %s", phase01.id)

            if phase01FinalFrame:
                niceNameOverride = "{0}_FinalFrame".format(niceName)
                byFrameOverride = 1
                phase01FinalFrameJob = submitJob(niceNameOverride, projectName,
                                                owner, jobStatus, compatabilityList,
                                                execName, baseCMDOverride, endFrame,
                                                endFrame, byFrameOverride, renderLayers,
                                                taskFile, int(priority * 1.25), phase,
                                                maxNodesP1, timeout, 10, jobType)

                logger.info("Phase 01 final frame workaround submitted with id: %s", phase01FinalFrameJob.id)

            phase01Status = True

        if self.finalCheckBox.isChecked():
            logger.info("Building Phase 02")
            #Phase specific overrides
            phase = 2
            byFrame = 1
            if phase01Status:
                jobStatusOverride = "U"
            else:
                jobStatusOverride = jobStatus

            phase02 = submitJob(niceName, projectName, owner, jobStatusOverride,
                                compatabilityList, execName, baseCMD, startFrame,
                                endFrame, byFrame, renderLayers, taskFile, priority,
                                phase, maxNodesP2, timeout, 10, jobType)

            logger.info("Phase 02 submitted with id: %s", phase02.id)

        self.submitButton.setEnabled(False)
        self.submitButton.setText("Job Submitted! Please close window.")