def __init__(self, name):
        self.locked = False
        self.name = name
        self.tempFilePath = os.path.join(BASEDIR, "{}.lock".format(self.name))
        self.tempFilePath = os.path.abspath(self.tempFilePath)
        logger.info("Temp File: %s", self.tempFilePath)

        #Windows
        if sys.platform == "win32":
            try:
                if os.path.exists(self.tempFilePath):
                    os.unlink(self.tempFilePath)
                    logger.debug("Unlink %s", self.tempFilePath)
                self.tempFile = os.open(self.tempFilePath, os.O_CREAT | os.O_EXCL | os.O_RDWR)
                self.locked = True
            except Exception as e:
                if e.errno == 13:
                    logger.error("Another Instance of %s is already running!", self.name)
                else:
                    logger.error(e)
        #Linux
        else:
            import fcntl
            self.tempFile = open(self.tempFilePath, "w")
            self.tempFile.flush()
            try:
                fcntl.lockf(self.tempFile, fcntl.LOCK_EX | fcntl.LOCK_NB)
                self.locked = True
            except IOError:
                logger.error("Another Instance of %s is already running", self.name)
Esempio n. 2
0
 def offlineThisNodeHandler(self):
     response = self.thisNode.offline()
     self.updateThisNodeInfo()
     if response:
         logger.info("Node Offlined")
     else:
         logger.error("Node could not be Offlined!")
Esempio n. 3
0
 def getOffThisNodeHandler(self):
     response = self.thisNode.getOff()
     self.updateThisNodeInfo()
     if response:
         logger.info("Node Offlined and Task Killed")
     else:
         logger.error("Node could not be Onlined or the Task could not be killed!")
Esempio n. 4
0
def softwareUpdater():
    hydraPath = os.getenv("HYDRA")

    if not hydraPath:
        logger.error("HYDRA enviromental variable does not exit!")
        return False

    hydraPath, thisVersion = os.path.split(hydraPath)
    try:
        currentVersion = float(thisVersion.split("_")[-1])
    except ValueError:
        logger.warning("Unable to obtain version number from file path. Assuming version number from Constants")
        currentVersion = Constants.VERSION

    versions = os.listdir(hydraPath)
    versions = [float(x.split("_")[-1]) for x in versions if x.startswith("dist_")]
    if not versions:
        return False
    highestVersion = max(versions)
    logger.debug("Comparing versions. Env: %s Latest: %s", currentVersion, highestVersion)
    if highestVersion > currentVersion:
        logger.info("Update found! Current Version is %s / New Version is %s", currentVersion, highestVersion)
        newPath = os.path.join(hydraPath, "dist_{}".format(highestVersion))
        response = changeHydraEnviron(newPath)
        if not response:
            logger.critical("Could not update to newest environ for some reason!")
        return response
    else:
        return False
Esempio n. 5
0
    def unstickTask(self):
        """Cleanup task if the node starts with one assigned to it
        (Like if the node crashed/restarted)"""
        #self.thisNode will be updated in in init statement
        if self.thisNode.task_id:
            logger.info("Rouge task discovered. Unsticking...")
            self.HydraTask = hydra_taskboard.fetch("WHERE id = %s", (self.thisNode.task_id,),
                                            cols=["id", "job_id", "renderLayer",
                                                    "status", "exitCode",
                                                    "endTime", "host",
                                                    "currentFrame"])
            self.HydraJob = hydra_jobboard.fetch("WHERE id = %s", (self.HydraTask.job_id,),
                                            cols=["jobType", "renderLayerTracker"])
            self.logPath = self.HydraTask.getLogPath()

            self.HydraTask.kill(CRASHED, False)

            self.progressUpdate()

            self.thisNode.status = IDLE if self.thisNode.status == STARTED else OFFLINE
            self.thisNode.task_id = None

        elif self.thisNode.status in [STARTED, PENDING]:
            logger.warning("Reseting bad status, node set %s but no task found!", self.thisNode.status)
            self.thisNode.status = IDLE if self.thisNode.status == STARTED else OFFLINE
Esempio n. 6
0
    def __init__(self):
        QMainWindow.__init__(self)
        self.setupUi(self)

        #Class Variables
        self.thisNodeName = Utils.myHostName()
        logger.info("This host is %s", self.thisNodeName)
        self.username = Utils.getInfoFromCFG("database", "username")
        self.userFilter = False
        self.showArchivedFilter = False
        self.statusMsg = "ERROR"
        self.currentJobSel = None

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

        #My UI Setup Functions
        self.setupTreeViews()
        self.connectButtons()
        self.setupHotkeys()
        self.setWindowIcon(QIcon(Utils.findResource("Images/FarmView.png")))

        #Make sure this node exists
        self.thisNodeButtonsEnabled = True
        self.thisNodeExists = self.findThisNode()

        #Setup Signals
        SIGNAL("doUpdate")
        QObject.connect(self, SIGNAL("doUpdate"), self.doUpdate)

        #Start autoUpdater and then fetch data from DB
        self.autoUpdateThread = stoppableThread(self.doUpdateSignaler, 10, "AutoUpdate_Thread")
        self.doFetch()
Esempio n. 7
0
 def tgt(self):
     while not self.stopEvent.is_set():
         #target = schedulerMain from the RenderNodeMainUI class
         self.interval = self.targetFunction()
         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)
Esempio n. 8
0
 def killTask(self, statusAfterDeath=KILLED):
     if self.status == "S" and self.task_id:
         taskOBJ = hydra_taskboard.fetch("WHERE id = %s", self.task_id,
                                         cols=["host", "status", "exitCode",
                                                 "endTime"])
         logger.debug("Killing task %d on %s", self.task_id, self.host)
         return taskOBJ.kill(statusAfterDeath, True)
     else:
         logger.info("No task to kill on %s", self.host)
         return True
Esempio n. 9
0
 def shutdown(self):
     logger.info("Shutting down...")
     if self.schedThreadStatus:
         self.schedThread.terminate()
     if self.autoUpdateStatus:
         self.autoUpdateThread.terminate()
     if self.renderServerStatus:
         self.renderServer.shutdown()
     logger.debug("All Servers Shutdown")
     self.trayIcon.hide()
     event.accept()
     sys.exit(0)
Esempio n. 10
0
    def update(self, trans):
        names = list(self.__dirty__)
        if not names:
            logger.info("Nothing to update on %s", self.tableName())
            return

        values = ([getattr(self, n) for n in names] + [getattr(self, self.primaryKey)])
        assignments = ", ".join(["{} = %s".format(n) for n in names])
        query = "UPDATE {0} SET {1} WHERE {2} = %s".format(self.tableName(), assignments, self.primaryKey)
        logger.debug((query, values))
        trans.cur.executemany(query, [values])
        return True
Esempio n. 11
0
 def startScheduleThread(self):
     """This is in it's own function because it starts and stops often"""
     #pylint: disable=W0703,W0201
     if bool(self.currentScheduleEnabled) and self.currentSchedule:
         self.schedThread = schedulerThread(self.schedulerMain,
                                             "Schedule_Thread", None)
         self.schedThreadStatus = True
         self.scheduleThreadPixmap.setPixmap(self.donePixmap)
         logger.info("Schedule Thread started!")
     else:
         logger.info("Schedule disabled. Running in manual control mode.")
         self.scheduleThreadPixmap.setPixmap(self.nonePixmap)
Esempio n. 12
0
def changeHydraEnviron(newEnviron):
    if sys.platform == "win32":
        logger.info("Changing Hydra Environ to %s", newEnviron)
        proc = subprocess.Popen(["setx", "HYDRA", newEnviron], stdout=subprocess.PIPE)
        out, _ = proc.communicate()
        if out.find("SUCCESS") > 0:
            os.environ["HYDRA"] = newEnviron
            return True
        else:
            logger.critical("Could not change enviromental variable!")
            return False
    else:
        raise "Not Implemented!"
Esempio n. 13
0
def main():
    logger.info("Starting in %s", os.getcwd())
    logger.info("arglist %s", sys.argv)

    #Check for other RenderNode isntances
    lockFile = InstanceLock("HydraRenderManager")
    lockStatus = lockFile.isLocked()
    logger.debug("Lock File Status: %s", lockStatus)
    if not lockStatus:
        logger.critical("Only one RenderManager is allowed to run at a time! Exiting...")
        sys.exit(-1)

    socketServer = RenderManagementServer()
    socketServer.createIdleLoop("Process_Render_Tasks_Thread",
                                socketServer.processRenderTasks,
                                interval=15)
Esempio n. 14
0
    def __init__(self):
        #Setup Class Variables
        self.renderThread = None
        self.childProcess = None
        self.PSUtilProc = None
        self.statusAfterDeath = None
        self.childKilled = 0
        self.HydraJob = None
        self.HydraTask = None
        self.logPath = None

        #Get this node data from the database and make sure it exists
        self.thisNode = getThisNodeOBJ()
        logger.debug(self.thisNode)
        if not self.thisNode:
            logger.critical(
                "This node does not exist in the database! Please Register this node and try again."
            )
            sys.exit(-1)
            return

        #Detect RedShift GPUs
        self.rsGPUs = Utils.getRedshiftPreference("SelectedCudaDevices")
        if self.rsGPUs:
            self.rsGPUs = self.rsGPUs.split(",")[:-1]
            self.rsGPUids = [x.split(":")[0] for x in self.rsGPUs]
            if len(self.rsGPUs) != len(self.rsGPUids):
                logger.warning("Problems parsing Redshift Preferences")
            logger.info("%s Redshift Enabled GPU(s) found on this node",
                        len(self.rsGPUs))
            logger.debug("GPUs available for rendering are %s", self.rsGPUs)
        else:
            logger.warning("Could not find available Redshift GPUs")

        #Create RenderLog Directory if it doesn't exit
        if not os.path.isdir(Constants.RENDERLOGDIR):
            os.makedirs(Constants.RENDERLOGDIR)

        self.unstickTask()
        self.thisNode.software_version = Constants.VERSION

        with transaction() as t:
            self.thisNode.update(t)

        #Run The Server
        port = int(Utils.getInfoFromCFG("network", "port"))
        self.startServerThread(port)
Esempio n. 15
0
    def getAverageRenderTime(self):
        totalTime = self.getTotalRenderTime()
        if totalTime:
            frameCount = self.getTotalFrameCount()
            frameTime = totalTime / frameCount
            seconds = int(frameTime.total_seconds())

        else:
            frameTimes = self.getEachFrameRenderTime()
            if not frameTimes:
                logger.info("Could not find any frame render times in %s", self.fp)
                return None
            #Add up seconds, divide by frame count
            seconds = sum([int(ft.total_seconds()) for ft in frameTimes]) / len(frameTimes)

        frameTime = datetime.timedelta(seconds=seconds)

        return frameTime
Esempio n. 16
0
 def nodeEditorHandler(self):
     response = self.nodeEditor()
     if response:
         logger.info("Updating this node...")
         logger.info("Node updated!")
     else:
         logger.info("No changes detected. Nothing was changed.")
Esempio n. 17
0
    def startupServers(self):
        logger.debug("Firing up main threads")
        #Start Render Server
        self.renderServer = RenderNode.RenderTCPServer()
        self.renderServerStatus = True
        self.renderServerPixmap.setPixmap(self.donePixmap)
        logger.info("Render Server Started!")

        #Start Pulse Thread
        self.renderServer.createIdleLoop("Pulse_Thread", pulse, 60)
        self.pulseThreadStatus = True
        self.pulseThreadPixmap.setPixmap(self.donePixmap)
        logger.info("Pulse Thread started!")

        #Start Auto Update Thread
        SIGNAL("updateThisNodeInfo")
        QObject.connect(self, SIGNAL("updateThisNodeInfo"), self.updateThisNodeInfo)
        self.autoUpdateStatus = True

        self.autoUpdateThread = stoppableThread(self.updateThisNodeInfoSignaler, 15,
                                                "AutoUpdate_Thread")
        self.startScheduleThread()
Esempio n. 18
0
def getInfoFromCFG(section, option):
    """Return information from the local configuration file."""
    config = ConfigParser.RawConfigParser()
    #Create a copy if it doesn't exist
    if not os.path.exists(Constants.SETTINGS):
        folder = os.path.dirname(Constants.SETTINGS)
        logger.info("Check for folder %s", folder)
        if os.path.exists(folder):
            logger.info("%s Exists", folder)
        else:
            logger.info("Make %s", folder)
            os.mkdir(folder)
        cfgFile = findResource(os.path.basename(Constants.SETTINGS))
        logger.info("Copy %s", cfgFile)
        shutil.copyfile(cfgFile, Constants.SETTINGS)

    config.read(Constants.SETTINGS)
    return config.get(section=section, option=option)
Esempio n. 19
0
 def shutdown(self):
     """Offline node, Kill current job, shutdown servers, reset node status"""
     currentStatus = self.thisNode.status
     self.thisNode.offline()
     if currentStatus in [STARTED, PENDING]:
         logger.info("Attempting to kill current job.")
         self.killCurrentJob(KILLED)
         logger.info("Kill Response Code: %s", self.childKilled)
     TCPServer.shutdown(self)
     #Online AFTER servers are shutdown
     if currentStatus == STARTED:
         self.thisNode.online()
     logger.info("RenderNode Servers Shutdown")
Esempio n. 20
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()
Esempio n. 21
0
    def killCurrentJob(self, statusAfterDeath):
        """Kills the render node's current job if it's running one.
        Return Codes: 1 = process killed, -1 = parent could not be killed,
        -9 = child could not be killed, -10 = child and parent could not be killed"""
        self.statusAfterDeath = statusAfterDeath
        self.childKilled = 1
        if not self.childProcess or not self.PSUtilProc:
            logger.info("No task is running!")
            return

        #Gather subprocesses just in case
        if self.PSUtilProc.is_running():
            childrenProcs = self.PSUtilProc.children(recursive=True)
        else:
            logger.info(
                "PID '%s' could not be found! Task is probably already dead.",
                self.childProcess.pid)
            return

        #Try to kill the main process
        #terminate() = SIGTERM, kill() = SIGKILL
        logger.info("Killing main task with PID %s", self.PSUtilProc.pid)
        self.PSUtilProc.terminate()
        _, alive = psutil.wait_procs([self.PSUtilProc], timeout=15)
        if len(alive) > 0:
            self.PSUtilProc.kill()
            _, alive = psutil.wait_procs([self.PSUtilProc], timeout=15)
            if len(alive) > 0:
                logger.error("Could not kill PID %s", self.PSUtilProc.pid)
                self.childKilled = -1

        #Try to kill the children if they are still running
        _ = [proc.terminate() for proc in childrenProcs if proc.is_running()]
        _, alive = psutil.wait_procs(childrenProcs, timeout=15)
        if len(alive) > 0:
            _ = [proc.kill() for proc in alive]
            _, alive = psutil.wait_procs(alive, timeout=15)

        if len(alive) > 0:
            #ADD negative 10 to the return code
            self.childKilled += -10
Esempio n. 22
0
        while not self.stopEvent.is_set():
            #target = schedulerMain from the RenderNodeMainUI class
            self.interval = self.targetFunction()
            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_()
Esempio n. 23
0
 def shutdownEvent(self):
     logger.info("Triggering Shutdown Event")
     self.offlineThisNodeHandler()
Esempio n. 24
0
 def startupEvent(self):
     logger.info("Triggering Startup Event")
     self.onlineThisNodeHandler()
Esempio n. 25
0
 def clearOutputHandler(self):
     choice = yesNoBox(self, "Confirm", "Really clear output?")
     if choice == QMessageBox.Yes:
         self.outputTextEdit.clear()
         logger.info("Output cleared")
Esempio n. 26
0
"""Registers a node with the database."""
#Standard
import os
import sys

#Third Party
#pylint: disable=E0611
from MySQLdb import IntegrityError

#Hydra
from Setups.LoggingSetup import logger
from Setups.MySQLSetup import hydra_rendernode, OFFLINE, transaction
import Utilities.Utils as Utils

if __name__ == "__main__":
    me = Utils.myHostName()
    hydraPath, execFile = os.path.split(sys.argv[0])
    logger.info(hydraPath)
    response = Utils.changeHydraEnviron(hydraPath)
    if response:
        try:
            with transaction() as t:
                hydra_rendernode(host=me, status=OFFLINE, minPriority=0).insert(t)
        except IntegrityError:
            logger.info("Host %s already exists in the hydra_rendernode table on the databse", me)
    else:
        logger.error("Could not set Hydra Environ! No changes where made. Exiting...")

    raw_input("\nPress enter to exit...")
Esempio n. 27
0
def storeCredentials(username, _password):
    keyring.set_password("Hydra", username, _password)
    logger.info("Password Stored in Credentials Vault")
Esempio n. 28
0
    def launchRenderTask(self, HydraJob, HydraTask):
        """Does the actual rendering, then records the results on the database"""
        logger.info("Starting task with id %s on job with id %s", HydraTask.id, HydraJob.id)
        self.HydraJob = HydraJob
        self.HydraTask = HydraTask
        self.childKilled = 0
        self.statusAfterDeath = None
        self.childProcess = None
        self.PSUtilProc = None

        originalCurrentFrame = int(self.HydraTask.currentFrame)
        renderTaskCMD = self.HydraTask.createTaskCMD(self.HydraJob, sys.platform)
        logger.debug(renderTaskCMD)

        self.logPath = self.HydraTask.getLogPath()
        logger.info("Starting render task %s", self.HydraTask.id)
        try:
            log = file(self.logPath, 'w')
        except (IOError, OSError, WindowsError) as e:
            logger.error(e)
            self.thisNode.getOff()
            return
        log.write('Hydra log file {0} on {1}\n'.format(self.logPath, self.HydraTask.host))
        log.write('RenderNode is {0}\n'.format(sys.argv))
        log.write('Command: {0}\n\n'.format(renderTaskCMD))
        Utils.flushOut(log)

        progressUpdateThread = stoppableThread(self.progressUpdate, 300,
                                                "Progress_Update_Thread")

        #Run the job and keep track of the process
        self.childProcess = subprocess.Popen(renderTaskCMD,
                                            stdout=log, stderr=log,
                                            **Utils.buildSubprocessArgs(False))

        logger.info("Started PID %s to do Task %s", self.childProcess.pid, self.HydraTask.id)

        self.PSUtilProc = psutil.Process(self.childProcess.pid)
        #Wait for task to finish
        self.childProcess.communicate()

        #Get Exit Code, Record the results
        self.HydraTask.exitCode = self.childProcess.returncode if self.childProcess else 1234
        logString = "\nProcess exited with code {0} at {1} on {2}\n"
        nowTime = datetime.datetime.now().replace(microsecond=0)
        log.write(logString.format(self.HydraTask.exitCode, nowTime,
                                    self.thisNode.host))

        progressUpdateThread.terminate()

        #Update HydraTask and HydraJob with currentFrame, MPF, and RLTracker
        self.progressUpdate(commit=False)

        #EndTime
        self.HydraTask.endTime = datetime.datetime.now()

        #Work around for batch files
        if self.HydraJob.jobType == "BatchFile" and self.HydraTask.exitCode == 0:
            self.HydraTask.currentFrame = (self.HydraTask.endFrame + 1)
            self.HydraJob.renderLayerTracker = str((self.HydraTask.endFrame + 1))

        #Status, Attempts. Failures
        if self.childKilled == 1:
            self.HydraTask.status = self.statusAfterDeath
            self.HydraTask.exitCode = 1

        else:
            if self.HydraTask.exitCode == 0 and self.HydraTask.currentFrame >= originalCurrentFrame:
                status = FINISHED
            else:
                if self.HydraTask.exitCode == 0:
                    log.write("\n\nERROR: Task returned exit code 0 but it appears to have not actually rendered any frames.")
                status = ERROR
                self.HydraJob.attempts += 1
                if not self.HydraJob.failures or self.HydraJob.failures == "":
                    self.HydraJob.failures = self.thisNode.host
                else:
                    self.HydraJob.failures += ",{0}".format(self.thisNode.host)

            self.HydraTask.status = status

        #Update data on the DB
        with transaction() as t:
            self.HydraTask.update(t)
            self.HydraJob.update(t)

        self.resetThisNode()
        log.close()
        logger.info("Done with render task %s", self.HydraTask.id)
        self.childProcess = None
        self.PSUtilProc = None
        self.HydraJob = None
        self.HydraTask = None
        self.logPath = None
Esempio n. 29
0
def loadCredentials(username):
    logger.info("Fetching login for %s", username)
    return keyring.get_password("Hydra", username)
Esempio n. 30
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.")