Example #1
0
class EngineManager(EngineObject):

    def __init__(self, id, mind, config, procman, user_pool=False):
        """need to add system spec in args
        """
        self.id = id
        self.mind = mind
        self.config = config
        self.procman = procman
        self.user_pool = user_pool
        self.interrupted = False
        self.client = None
        #d = self.mind.callRemote('getSystem')
        #d.addCallback(self.start)
        #self.start()

    def start(self, system):
        self.defer_ready = defer.Deferred()
        if system == 'python':
            from knoboo.kernel.engine.python import runtime
        elif system == 'sage':
            from knoboo.kernel.engine.sage import runtime
        if self.user_pool:
            try:
                self.uid = self.user_pool.pop()
                self.gid = self.user_pool.gid
            except IndexError:
                return 'Max users exceeded. Try again later.'
        else:
            self.uid = self.config['engines-uid']
            self.gid = self.uid
        process_setup = runtime.ProcessSetup(self.config, self.id, self.uid, self.gid)
        self.control = EngineProcessControl()
        self.control.buildProcess(process_setup)
        self.control.manager = self
        self.procman.addProcess(self.control)
        return self.defer_ready

    def stop(self):
        self.procman.removeProcess(self.id)

    def processStarted(self, port):
        url = 'http://localhost:' + port
        self.client = RPCClient(url)
        d = self.client.callRemote('hello')
        d.addCallback(self._engine_ready)
        return d

    def processStopped(self):
        """if the process stops for any reason, the process protocol will
        call this function.
        """
        if self.user_pool:
            self.user_pool.append(self.uid)

    def _engine_ready(self, res):
        self.client.callRemote('interpreter_go')
        self.defer_ready.callback('ok')

    def interrupt(self):
        di = self.control.interrupt()
        d = self.call('cancel_interrupt')
        d.addCallback(self._cancel_interrupt_callback)
        d.addErrback(self._cancel_interrupt_errback)
        self.set_interrupted()
        return d

    def set_interrupted(self):
        self.interrupted = True

    def cancel_interrupt(self):
        self.interrupted = False
        self.control.cancel_interrupt()

    def _cancel_interrupt_callback(self, result):
        #self.control.cancel_interrupt()
        return 'ok' 

    def _cancel_interrupt_errback(self, reason):
        return 'fail'

    def call(self, method, *args):
        """wrapper around callRemote
        """
        d = self.client.callRemote(method, *args)
        d.addCallback(self.clientCallback)
        d.addErrback(self.clientErrback)
        return d

    def clientCallback(self, result):
        """First callback after engine returns
        """
        if self.interrupted:
            self.cancel_interrupt()
        return self.output_type(result)

    def clientErrback(self, res):
        return res


    def output_type(self, output):
        """determine what the output is so eventually the browser can properly
        display it.
        """
        image_preface = "__imagefile__"
        out = output['out']
        if image_preface in out:
            image_path = out[13:]
            image_path = image_path.strip('\n')
            f = file(image_path, 'r')
            image = f.read()
            f.close()
            os.remove(image_path)
            image_name = os.path.basename(image_path)
            web_path = os.path.join('/images', image_name)
            web_path = '__image__' + web_path
            output['out'] = web_path
            d = self.mind.callRemote('writeImage', image, image_name) 
            d.addCallback(self._output_type_callback, output)
            return d
        return output

    def _output_type_callback(self, result, output):
        return output
Example #2
0
 def processStarted(self, port):
     url = 'http://localhost:' + port
     self.client = RPCClient(url)
     d = self.client.callRemote('hello')
     d.addCallback(self._engine_ready)
     return d