Ejemplo n.º 1
0
    def __init__(self):
        """
        Initialize render node
        """

        SignalThread.__init__(self, name='RenderNodeThread')

        self.stop_flag = False
        self.uuid = None
        self.currentTask = None
        self.host_info = self.collectHostInfo()

        self.taskSender = TaskSender(self)
Ejemplo n.º 2
0
class RenderNode(SignalThread):
    """
    Render node implementation
    """

    def __init__(self):
        """
        Initialize render node
        """

        SignalThread.__init__(self, name='RenderNodeThread')

        self.stop_flag = False
        self.uuid = None
        self.currentTask = None
        self.host_info = self.collectHostInfo()

        self.taskSender = TaskSender(self)

    def collectHostInfo(self):
        """
        Collect all host-specific info
        """

        info = {}

        if Config.slave['send_host_info']:
            import platform
            import os

            info['hostname'] = socket.gethostname()
            info['arch'] = platform.architecture()[0]

            cores = 1
            if hasattr(os, 'sysconf'):
                if 'SC_NPROCESSORS_ONLN' in os.sysconf_names:
                    cores = os.sysconf('SC_NPROCESSORS_ONLN')

            info['cores'] = cores
            info['platform'] = ' '.join(os.uname()).strip()
            info['dist'] = ' '.join(platform.dist()).strip()

        return info

    def getUUID(self):
        """
        Get node's UUID
        """

        return self.uuid

    def requestStop(self):
        """
        Stop node
        """

        self.stop_flag = True

    def isStopped(self):
        """
        Check if node shutted down
        """

        return self.stop_flag

    def register(self):
        """
        Register node at master
        """

        if self.uuid is not None:
            return

        proxy = slave.Slave().getProxy()

        try:
            self.uuid = proxy.node.register(self.host_info)
            Logger.log('Registered at master under uuid {0}' .
                format(self.uuid))
        except socket.error as strerror:
            Logger.log('Error registering self: {0}'. format(strerror))
        except:
            Logger.log('Unexpected error: {0}' . format(sys.exc_info()[0]))
            raise

    def unregister(self):
        """
        Unregister node from renderfarm master
        """

        if not self.uuid:
            # Not registered at server -- no need in unregistering
            return

        proxy = slave.Slave().getProxy()

        try:
            proxy.node.unregister(self.uuid)
            self.uuid = None
            Logger.log('Node unregisered')
        except socket.error as strerror:
            Logger.log('Error registering self: {0}'. format(strerror))
        except:
            Logger.log('Unexpected error: {0}' . format(sys.exc_info()[0]))
            raise

    def check(self):
        """
        Check if node still walid
        """

        if self.uuid is None:
            return False

        proxy = slave.Slave().getProxy()

        try:
            return proxy.node.check(self.uuid)
        except socket.error as strerror:
            Logger.log('Error checking self: {0}'. format(strerror))
        except:
            Logger.log('Unexpected error: {0}' . format(sys.exc_info()[0]))
            raise

        return False

    def touch(self):
        """
        Touch master to tell we're still alive
        """

        # Ensure we're registered at serevr
        if not self.check():
            if self.uuid is not None:
                Logger.log('Connection to server lost, registering again...')
                self.uuid = None
            self.register()

        if self.uuid is None:
            # Not registered at server
            return

        proxy = slave.Slave().getProxy()

        try:
            proxy.node.touch(self.uuid)
        except socket.error as strerror:
            Logger.log('Error touching master: {0}'. format(strerror))
        except:
            Logger.log('Unexpected error: {0}' . format(sys.exc_info()[0]))
            raise

    def requestTask(self):
        """
        Request task from master
        """

        if self.currentTask is not None:
            # Already got task
            return

        if not self.uuid:
            # Nowhere to request from
            return

        proxy = slave.Slave().getProxy()

        try:
            options = proxy.job.requestTask(self.uuid)
            if options:
                Logger.log('Got new task {0} for job {1}' .
                    format(options['task'], options['jobUUID']))
                self.currentTask = spawnNewTask(options)
        except socket.error as strerror:
            Logger.log('Error requesting task: {0}'. format(strerror))
        except:
            Logger.log('Unexpected error: {0}' . format(sys.exc_info()[0]))
            raise

    def sendRenderedImage(self):
        """
        Send rendered image to selver
        """

        self.taskSender.sendTask(self.currentTask)

    def restoreTask(self):
        """
        Restart assigned task on master
        """

        jobUUID = self.currentTask.getJobUUID()
        task_nr = self.currentTask.getTaskNum()

        Logger.log('Error occured while rendering task {0} of job {1}' .
            format(task_nr, jobUUID))

        proxy = slave.Slave().getProxy()

        proxy.job.restartTask(self.uuid, jobUUID, task_nr)

    def sendResult(self):
        """
        Send result to master
        """

        if not self.currentTask.hasError():
            self.sendRenderedImage()
        else:
            self.restoreTask()

        self.currentTask = None

    def run(self):
        """
        Main cycle of render node
        """

        Logger.log('Started main render node thread')

        self.taskSender.start()

        last_touch_time = last_request_time = time.time()
        first_time = True

        touch_int = Config.slave['touch_interval']
        req_int = Config.slave['job_request_interval']

        while not self.stop_flag:
            cur_time = time.time()

            if first_time or cur_time - last_touch_time >= touch_int:
                self.touch()
                last_touch_time = cur_time

            if first_time or \
               cur_time - last_request_time >= req_int:
                self.requestTask()
                last_request_time = cur_time

            if self.currentTask is not None:
                if not self.currentTask.isAlive():
                    if not self.currentTask.isFinished():
                        self.currentTask.start()
                    else:
                        self.sendResult()

                        # Request next task just after render finish
                        # it should save a bit of time
                        self.requestTask()
                        last_request_time = cur_time

            first_time = False

            time.sleep(0.2)

        # Wait all tasks to be sent to master
        self.taskSender.requestStop()
        self.taskSender.join()

        # Unregister
        self.unregister()

        Logger.log('Main render node thread was stopped')