def _deleteJob(self): if self.job_id is not None: if self['keep_job_on_cancel_cook'].evaluateInt(): af.Cmd().stopJobById(self.job_id) else: af.Cmd().deleteJobById(self.job_id) self._initData()
def onSchedule(self, work_item): """ [virtual] onSchedule(self, pdg.WorkItem) -> pdg.SchedulerResult This callback is evaluated when the given pdg.WorkItem is ready to be executed. """ if len(work_item.command) == 0: return pdg.scheduleResult.CookSucceeded self._log('onSchedule input: {} - {}'.format(work_item.node.name, work_item.name)) # Ensure directories exist and serialize the work item self.createJobDirsAndSerializeWorkItems(work_item) # Create a task: task = self._constructTask(work_item) # Check that a block for the current TOP node exists: if not work_item.node.name in self.job_block_name_id: # We need to append a new block to the job, # as this is the first work item of a current TOP node. block = self._constructBlock(work_item) block.tasks.append(task) block_id = 0 if self.job_id is None: # This is probably the first onSchedule call. # The job was not created. job = self._constructJob() job.blocks.append(block) if not self._sendJob(job): return pdg.scheduleResult.CookFailed else: # Append a new block to the job struct = af.Cmd().appendBlocks(self.job_id, [block]) if not 'block_ids' in struct['object']: self._log('Error appending block:\n' + str(struct)) return pdg.scheduleResult.Failed block_id = struct['object']['block_ids'][0] self.job_block_name_id[work_item.node.name] = block_id self.job_tasks_id_workid[block_id] = {} self.job_tasks_id_workid[block_id][0] = work_item.id else: # Current TOP node block exists, we need just to append the task block_id = self.job_block_name_id[work_item.node.name] struct = af.Cmd().appendTasks(self.job_id, block_id, [task]) if not 'task_ids' in struct['object']: self._log('Error appending task:\n' + str(struct)) return pdg.scheduleResult.Failed task_id = struct['object']['task_ids'][0] self.job_tasks_id_workid[block_id][task_id] = work_item.id return pdg.scheduleResult.Succeeded
def submit(): input_rops = [i[0] for i in hou.pwd().inputDependencies()] rop_list = [] job_ids = [] cmd = af.Cmd() for rop in input_rops: rop.parm('af_offline_job').set(1) rop.parm('af_ubmit').pressButton() rop.parm('af_job_info_pretty').eval() rop_list.append(rop.evalParm('af_job_info_pretty')) rop.parm('af_offline_job').set(0) for i in range(len(rop_list)): cmd.data['mask'] = rop_list[i] job = cmd.getJobList() id = job[0]['id'] job_ids.append(id) if i > 0: cmd.action = 'action' cmd.data['type'] = 'jobs' cmd.data['mask'] = rop_list[i] cmd.data['params'] = {'depend_mask': rop_list[i - 1]} cmd._sendRequest() job_ids.reverse() for id in job_ids: cmd.setJobState(id, 'start')
def get_afanasy_hostnames(): import af hostnames = [] cmd = af.Cmd() clients = cmd.renderGetList() for client in clients: hostnames.append(client["name"]) return hostnames
def setUserDialog(): name, ok = QtWidgets.QInputDialog.getText( None, 'Set Render User', 'Ender New Name:', text=cgruconfig.VARS['USERNAME'] ) if not ok: return af.Cmd().renderSetUserName( name) refreshAfter()
def refresh(): global Render global RenderFull if Render is None: # Get render by local host name renders = af.Cmd().renderGetLocal() if renders is not None and len(renders): Render = renders[0] if Render is not None: # Get render by ID, as we already know it obj = af.Cmd().renderGetId(Render['id'],'full') if obj is not None and 'object' in obj and 'render' in obj['object']: RenderFull = obj['object'] Render = RenderFull['render'] if Refresh: Refresh.setDefaultInterval() else: if obj is None: print('ERROR: NULL object reveived.') elif 'info' in obj: obj = obj['info'] if obj['kind'] == 'error': print('ERROR: %s' % obj['text']) else: print('%s: %s' % (obj['kind'], obj['text'])) else: print('ERROR: Unexpected object reveived:') print(json.dumps(RenderFull, sort_keys=True, indent=4)) # "Reset" render information, if failed to reveive it # Most probably render was deleted, # and there is no more render with such ID Render = None RenderFull = None # Increase refresh interval by 10 times if Refresh: Refresh.setIntervalKoeff(10) cmd.Tray.showIcon( makeIcon()) cmd.Tray.updateToolTip(makeTip())
def onTick(self): """ [virtual] Called during a cook. Checks on jobs in flight to see if any have finished. """ # check that the job was created if self.job_id is None: # OnTick can be called before onSchedule! # Before onSchedule job is not created/sent return pdg.tickResult.SchedulerReady # get job progress job_progress = af.Cmd().getJobProgress(self.job_id) if job_progress is None: self._log('Error getting job progress.') return pdg.tickResult.SchedulerBusy job_progress = job_progress['progress'] ids_to_del = {} for block_id in self.job_tasks_id_workid: ids_to_del[block_id] = [] for task_id in self.job_tasks_id_workid[block_id]: work_item_id = self.job_tasks_id_workid[block_id][task_id] task_progress = job_progress[block_id][task_id] state = task_progress['state'] if state.find('RUN') != -1: self.onWorkItemStartCook(work_item_id, -1) elif state.find('ERR') != -1: if self['report_fail_on_error'].evaluateInt(): self.onWorkItemFailed(work_item_id, -1) # If the graph is setup to block on failures, then # we continue to track the task if not self.isWaitForFailures: ids_to_del[block_id].append(task_id) elif state.find('SKP') != -1: self.onWorkItemCanceled(work_item_id, -1) ids_to_del[block_id].append(task_id) elif state.find('DON') != -1: time_started = task_progress['tst'] time_done = task_progress['tdn'] cook_time = float(time_started - time_done) self.onWorkItemSucceeded(work_item_id, -1, cook_time) ids_to_del[block_id].append(task_id) for block_id in ids_to_del: for task_id in ids_to_del[block_id]: del self.job_tasks_id_workid[block_id][task_id] return pdg.tickResult.SchedulerReady
def refresh(): global Render global RenderFull if Render is None: renders = af.Cmd().renderGetLocal() if renders is not None and len(renders): Render = renders[0] if Render is not None: obj = af.Cmd().renderGetId(Render['id'],'full') if obj is not None and 'object' in obj and 'render' in obj['object']: RenderFull = obj['object'] Render = RenderFull['render'] else: print('ERROR: Unexpected object reveived:') print(json.dumps(RenderFull, sort_keys=True, indent=4)) cmd.Tray.showIcon( makeIcon())
def request_renderclients(): client_list = [] cmd = af.Cmd() clients = cmd.renderGetList() for client in clients: name = client['name'] # version = client['engine'] address = client['address'] ip = address['ip'] port = address['port'] client_list.append(AF_RenderClient(name, "", ip, port)) return client_list
def refresh(): renders = af.Cmd().renderGetLocal() if renders is not None and len(renders): render = renders[0] if "state" in render: online = render["state"].find('OFF') == -1 nimby = render["state"].find('NbY') != -1 NIMBY = render["state"].find('NBY') != -1 busy = render["state"].find('RUN') != -1 cmd.Tray.showRenderIcon(online, nimby or NIMBY, busy) else: cmd.Tray.showIcon()
def showInfo(tray=None): renders = af.Cmd().renderGetLocal() if renders is None or len(renders) == 0: if tray is not None: tray.showMessage('Render information:', 'No local render client found.') return global WndInfo WndInfo = QtGui.QTextEdit() WndInfo.setPlainText(json.dumps(renders[0], sort_keys=True, indent=4)) WndInfo.setReadOnly(True) WndInfo.resize(WndInfo.viewport().size()) WndInfo.setWindowTitle('AFANASY Render Information:') WndInfo.show()
def setNIMBY(text='(keeper)'): cmd = af.Cmd().renderSetNIMBY(text)
def setFree(text='(keeper)'): cmd = af.Cmd().renderSetFree(text)
def ejectNotMyTasks(text='(keeper)'): cmd = af.Cmd().renderEjectNotMyTasks(text) render.refreshAfter()
def setnimby(text='(keeper)'): cmd = af.Cmd().renderSetNimby(text)
def evaluateCmd(self, i_start=False): if not self.constructed: return self.evaluated = False self.bStart.setEnabled(False) # self.fileChange() # Check parameters: # Frame range: framestart = self.fields['framestart'].value() frameend = self.fields['frameend'].value() frameby = self.fields['frameby'].value() framespt = self.fields['framespt'].value() if i_start: if framestart > frameend: QtWidgets.QMessageBox.critical( self, 'Critical', 'First frame is greater that last.') return tasksnum = (1.0 + frameend - framestart) / (1.0 * frameby * framespt) if tasksnum > 10000.0: answer = QtWidgets.QMessageBox.warning( self, 'Warning', 'Number of tasks > 10000', QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.Abort) if answer != QtWidgets.QMessageBox.Yes: return if tasksnum > 100000.0: answer = QtWidgets.QMessageBox.warning( self, 'Warning', 'Number of tasks > 100000', QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.Abort) if answer != QtWidgets.QMessageBox.Yes: return if tasksnum > 1000000.0: self.teCmd.setText( 'The number of tasks over one million. Call you system ' 'administrator, supervisor or TD.') return # Check wdir: if self.fields['scenewdir'].isChecked(): self.fields['wdir'].setEnabled(False) else: self.fields['wdir'].setEnabled(True) # Set job name: if self.fields['jobnamescene'].isChecked(): self.fields['jobname'].setText( os.path.basename(str(self.fields['scenefile'].text()))) self.fields['jobname'].setEnabled(False) else: self.fields['jobname'].setEnabled(True) # Check scene: scene = str(self.fields['scenefile'].text()) if len(scene) == 0: return name, ext = os.path.splitext(scene) if ext in ScenesSequences: scene = afcommon.patternFromFile(scene) elif not os.path.isfile(scene): self.teCmd.setText('Scene file does not exist.') return scene = os.path.normpath(scene) scene = os.path.abspath(scene) self.fields['scenefile'].setText(scene) # Check working directory: if self.fields['scenewdir'].isChecked(): self.fields['wdir'].setText( os.path.dirname(str(self.fields['scenefile'].text()))) if not os.path.isdir(self.fields['wdir'].text()): self.teCmd.setText('Working directory does not exist.') return self.fields['wdir'].setText( os.path.abspath(str(self.fields['wdir'].text()))) # Check job name: if str(self.fields['jobname'].text()) == '': self.teCmd.setText('Job name is empty.') return # Get File Type Override servType = getComboBoxString(self.fields['servicetype']) # Construct command: cmd = os.environ['AF_ROOT'] cmd = os.path.join(cmd, 'python') cmd = os.path.join(cmd, 'afjob.py') cmd = '"%s" "%s"' % (os.getenv('CGRU_PYTHONEXE', 'python'), cmd) cmd += ' "%s"' % self.fields['scenefile'].text() cmd += ' %d' % self.fields['framestart'].value() cmd += ' %d' % self.fields['frameend'].value() cmd += ' -by %d' % self.fields['frameby'].value() cmd += ' -fpt %d' % self.fields['framespt'].value() cmd += ' -seq %d' % self.fields['frameseq'].value() if not str(self.fields['node'].text()) == '': cmd += ' -node "%s"' % self.fields['node'].text() if not str(self.fields['take'].text()) == '': cmd += ' -take "%s"' % self.fields['take'].text() if not str(self.fields['outimages'].text()) == '': cmd += ' -output "%s"' % self.fields['outimages'].text() if not str(self.fields['preview'].text()) == '': cmd += ' -images "%s"' % self.fields['preview'].text() if not str(self.fields['extrargs'].text()) == '': cmd += ' -extrargs "%s"' % self.fields['extrargs'].text() if len(servType) and servType != 'none': cmd += ' -type "%s"' % servType if str(self.fields['os'].text()) == '': cmd += ' -os any' else: cmd += ' -os "%s"' % self.fields['os'].text() cmd += ' -pwd "%s"' % self.fields['wdir'].text() if self.fields['capacity'].value() > 0: cmd += ' -capacity %d' % self.fields['capacity'].value() if self.fields['maxruntasks'].value() > 0: cmd += ' -maxruntasks %d' % self.fields['maxruntasks'].value() if self.fields['maxtasksperhost'].value() > 0: cmd += ' -maxtasksperhost %d' % self.fields[ 'maxtasksperhost'].value() if self.fields['priority'].value() > -1: cmd += ' -priority %d' % self.fields['priority'].value() if not str(self.fields['dependmask'].text()) == '': cmd += ' -depmask "%s"' % self.fields['dependmask'].text() if not str(self.fields['dependglobal'].text()) == '': cmd += ' -depglbl "%s"' % self.fields['dependglobal'].text() if not str(self.fields['hostsmask'].text()) == '': cmd += ' -hostsmask "%s"' % self.fields['hostsmask'].text() if not str(self.fields['hostsexclude'].text()) == '': cmd += ' -hostsexcl "%s"' % self.fields['hostsexclude'].text() # Render Pools Additon if str(self.cbSelectedPool.currentText() != "Don't use pool."): for pool in self.pools: if pool["name"] == self.cbSelectedPool.currentText(): afanasy_hostnames = [] included_hostnames = [] excluded_hostnames = [] # get afanasy hostnames afModuleCmd = af.Cmd() af_clients = afModuleCmd.renderGetList() for af_client in af_clients: afanasy_hostnames.append(af_client["name"]) # get included hostnames clients = pool["clients"] for client in clients: included_hostnames.append(client["hostname"]) # compute excluded hosts for af_hostname in afanasy_hostnames: if not af_hostname in included_hostnames: excluded_hostnames.append(af_hostname) # generate host exclude mask regex_mask = "" for excluded_hostname in excluded_hostnames: regex_mask += excluded_hostname + "|" if regex_mask.endswith("|"): regex_mask = regex_mask[:-1] if regex_mask != "": cmd += ' -hostsexcl "%s"' % regex_mask if self.fields['paused'].isChecked(): cmd += ' -pause' cmd += ' -name "%s"' % self.fields['jobname'].text() if not str(self.fields['exec'].text()) == '': cmd += ' -exec "%s"' % self.fields['exec'].text() # Evaluated: self.teCmd.setText(cmd) self.evaluated = True self.bStart.setEnabled(True) print('Evaluated')
def exitTalk( text = '(keeper)'): af.Cmd().talkExit( text) def exitMonitor( text = '(keeper)'): af.Cmd().monitorExit( text)
def ejectNotMyTasks(text='(keeper)'): cmd = af.Cmd().renderEjectNotMyTasks(text)
def ejectAndNIMBY(): cmd = af.Cmd().renderEjectAndNIMBY() render.refreshAfter()
def setNIMBY(): cmd = af.Cmd().renderSetNIMBY() render.refreshAfter()
def setnimby(): cmd = af.Cmd().renderSetNimby() render.refreshAfter()
# Example of use of Afanasy's API to generate a summary of the state of the # render farm. # Copyright (c) 2016 rise|fx (Elie Michel) - Released under MIT License import af cmd = af.Cmd() def isSysJob(job): return job['st'] == 0 ## Jobs ## joblist = cmd.getJobList() job_state_counters = {} job_count = 0 for job in joblist: if isSysJob(job): continue job_count += 1 for s in job['state'].split(): job_state_counters[s] = job_state_counters.get(s, 0) + 1 print("Out of %d jobs:" % job_count) print(" * %d are running" % job_state_counters.get('RUN', 0)) print(" * %d have error" % job_state_counters.get('ERR', 0)) print(" * %d are skipped" % job_state_counters.get('SKP', 0))
def setFreeUnpause(): cmd = af.Cmd().renderSetFreeUnpause() render.refreshAfter()
def exitRender(): af.Cmd().renderExit()
def ejectNotMyTasks(): cmd = af.Cmd().renderEjectNotMyTasks() render.refreshAfter()
def exitMonitor(): af.Cmd().monitorExit()
def exitRender( text = '(keeper)'): af.Cmd().renderExit( text) def exitTalk( text = '(keeper)'): af.Cmd().talkExit( text)
def setnimby(text='(keeper)'): cmd = af.Cmd().renderSetNimby(text) render.refreshAfter()
def exitMonitor( text = '(keeper)'): af.Cmd().monitorExit( text) def exitClients( text = '(keeper)'):
def setFree(text='(keeper)'): cmd = af.Cmd().renderSetFree(text) render.refreshAfter()