Beispiel #1
0
 def on_open(self, info):
     global logger
     self.is_authenticated = False
     if not SRVR_CFG.multiuser:
         self.sess = SessionStandalone(getpass.getuser())
     else:
         self.sess = None
     logger.debug("%s websocket connection opened", self.log_str())
Beispiel #2
0
class WebSocketHandler(sockjs.tornado.SockJSConnection):
    def log_str(self):
        return self.sess.log_str() if (None != self.sess) else ''
        
    def on_open(self, info):
        global logger
        self.is_authenticated = False
        if not SRVR_CFG.multiuser:
            self.sess = SessionStandalone(getpass.getuser())
        else:
            self.sess = None
        logger.debug("%s websocket connection opened", self.log_str())

    def on_close(self):
        global logger
        self.is_authenticated = False
        logger.debug("%s websocket connection closed", self.log_str())
        
        sess = self.sess
        if (sess != None) and (sess.task != None) and sess.detach:
            logger.debug("%s detaching task", self.log_str())
            self.sess.task.detach()

    def logout_or_detach(self):
        sess = self.sess
        if SRVR_CFG.multiuser and (sess != None):
            logger.debug("%s in logout_or_detach detach=%s task: %s", self.log_str(), str(sess.detach), str(sess.task == None))
            if (not sess.detach) or (sess.task == None):
                sess.logout()
                self.sess = None
        

    def on_message(self, message):
        global SRVR_CFG
        #logger.debug("got request url " + self.request.full_url())
        #logger.debug("websocket message received [%s]"%(str(message),))
        wsmsg = WSMsg(msg=message, handler=self)
        logger.debug('%s received msg_type: %d, data[%s]', self.log_str(), wsmsg.nv['msg_type'], str(wsmsg.nv['data']))
        is_shutdown_msg = False
        response = {}
        try:
            if SRVR_CFG.multiuser and not self.is_authenticated:
                response, is_shutdown_msg = self.handle_auth(wsmsg)
            else:
                if (wsmsg.msg_type() == WSMsg.REQ_FILE_LIST) and not SRVR_CFG.multiuser:
                    response, is_shutdown_msg = self.handle_file_list(wsmsg)
                elif (wsmsg.msg_type() == WSMsg.REQ_LOGOUT):
                    response, is_shutdown_msg = self.handle_logout(wsmsg)
                elif (wsmsg.msg_type() == WSMsg.REQ_RUN_VERIFY):
                    response, is_shutdown_msg = self.handle_run_verify(wsmsg)
                elif (wsmsg.msg_type() == WSMsg.REQ_RUN_JOB):
                    response, is_shutdown_msg = self.handle_run_job(wsmsg)
                elif (wsmsg.msg_type() == WSMsg.REQ_RUN_BATCH):
                    response, is_shutdown_msg = self.handle_run_batch(wsmsg)
                elif (wsmsg.msg_type() == WSMsg.REQ_ABORT_JOB):
                    response, is_shutdown_msg = self.handle_abort_job(wsmsg)
                elif (wsmsg.msg_type() == WSMsg.REQ_LOAD_CFG):
                    response, is_shutdown_msg = self.handle_load_config(wsmsg)
                elif (wsmsg.msg_type() == WSMsg.REQ_DETACH_TASK):
                    response, is_shutdown_msg = self.handle_detach_task(wsmsg)
                elif (wsmsg.msg_type() == WSMsg.REQ_ATTACH_TASK):
                    response, is_shutdown_msg = self.handle_attach_task(wsmsg)
                elif (wsmsg.msg_type() == WSMsg.REQ_DETACHED_TASKS):
                    response, is_shutdown_msg = self.handle_detached_tasks(wsmsg)
                elif (wsmsg.msg_type() == WSMsg.REQ_LAST_RUN_LOG):
                    response, is_shutdown_msg = self.handle_last_run_log(wsmsg)

            if response != None:
                logger.debug("%s responding with message: %s", self.log_str(), str(response))
                wsmsg.reply(response)
        except Exception:
            logger.exception("%s Exception handling message of type %d", self.log_str(), wsmsg.msg_type())
            wsmsg.error(-1)
            
        if is_shutdown_msg:
            if SRVR_CFG.multiuser:
                self.logout_or_detach()
            else:
                stop_webserver()

    def handle_auth(self, wsmsg):
        if (not self.is_authenticated) and (wsmsg.msg_type() == WSMsg.REQ_AUTH):
            self.sess_id = wsmsg.data('sess_id')
            self.sess = sess = Session.get_session(self.sess_id)
            self.is_authenticated = (sess != None)
            if self.is_authenticated:
                sess.detach = True  # set detach mode by default
                self.work_dir = sess.work_dir()
                self.storage_creds, self.store = sess.storage()
                msg = None
            else:
                msg = 'Your login session appears to have timed out. Please sign in again.'
            return ({'success': self.is_authenticated, 'msg': msg}, not self.is_authenticated)
        return (None, not self.is_authenticated)
        

    def handle_load_config(self, wsmsg):
        global SRVR_CFG
        result = None
        success = False
        try:
            filepath = wsmsg.data('filename')
            logger.debug("%s handle_load_config filepath: %s", self.log_str(), filepath)
            if SRVR_CFG.multiuser:
                logger.debug("%s translating filepath to local in multiuser mode", self.log_str())
                filepath = self.store.copy_to_local(filepath, self.work_dir)
            logger.debug("%s handle_load_config filepath: %s", self.log_str(), filepath)
            
            cfg = CSConfig(filepath)
            
            if SRVR_CFG.multiuser:
                result = cfg.as_dict()
            else:
                filedir, _filename = os.path.split(filepath)
                result = cfg.as_dict(rel_to_abs=filedir)
            success = True
        except Exception as e:
            logger.exception("%s Error reading configuration from %s", self.log_str(), wsmsg.data('filename'))
            result = 'HttpError' if isinstance(e, HttpError) else 'UnknownError'
        logger.debug("%s returning config [%s]", self.log_str(), str(result))
        return ({'cfg': result, 'success': success}, False)


    def handle_attach_task(self, wsmsg):
        self.sess.detach = True
        task = self.sess.task
        if None != task:
            wsmsg.reply({'success': True, 'client_ctx': task.client_ctx})
            task.attach(self)
            return (None, False)
        return ({'success': False}, False)


    def handle_detached_tasks(self, wsmsg):
        num_tasks = 1 if (self.sess.task != None) else 0
        return ({'success': True, 'num_tasks': num_tasks}, False)
    

    def handle_detach_task(self, wsmsg):
        self.sess.detach = True
        return ({'success': True}, False)

    def handle_last_run_log(self, wsmsg):
        run_log = Utils.open_last_run_log("", self.sess.user_id())
        if None == run_log:
            return ({'success': False, 'msg': "No run logs found."}, False)
        
        resp_nv = {
                   'msg_type': BaseMsg.SHOW_LOG,
                   'data': ''
        }
        success = False
        try:
            for line in run_log.readlines():
                resp_nv['data'] = line.rstrip()
                self.send(resp_nv, False)
            success = True
        finally:
            run_log.close()
        return ({'success': success}, False)

    def handle_abort_job(self, wsmsg):
        if self.sess.task != None:
            self.sess.task.abort()
        return (None, False)


    def _make_wslogger(self):
        wslogger = WebSocketLogger(self)
        if SRVR_CFG.multiuser:
            tee_file = open(os.path.join(self.sess.local_work_dir, "run.log"), "w")
            wslogger.tee(tee_file)
        return wslogger


    def handle_run_job(self, wsmsg):
        if self.sess.task != None:
            wsmsg.error("Your background task is still running. Wait for it to complete before starting another.")
            return (None, False)
        
        global SRVR_CFG
        wslogger = self._make_wslogger()
        multiuser = SRVR_CFG.multiuser
        if multiuser:
            work_dir = self.work_dir
            storage_creds = self.storage_creds
            user_role = self.sess.user_role()
        else:
            work_dir = storage_creds = None
            user_role = 'standalone'
            
        data = wsmsg.nv['data']
        run_data = data['run_data']
        client_ctx = data['client_ctx']
        self.sess.task = CircuitscapeRunner(wslogger, wsmsg, CircuitscapeRunner.run_job, client_ctx, user_role, run_data, work_dir, storage_creds, multiuser, self.sess.log_str())
        return (None, False)


    def handle_run_batch(self, wsmsg):
        if self.sess.task != None:
            wsmsg.error("Your background task is still running. Wait for it to complete before starting another.")
            return (None, False)
        
        global SRVR_CFG
        wslogger = self._make_wslogger()
        multiuser = SRVR_CFG.multiuser
        if multiuser:
            work_dir = self.work_dir
            storage_creds = self.storage_creds
            user_role = self.sess.user_role()
        else:
            work_dir = storage_creds = None
            user_role = 'standalone'
            
        data = wsmsg.nv['data']
        run_data = data['run_data']
        client_ctx = data['client_ctx']
        self.sess.task = CircuitscapeRunner(wslogger, wsmsg, CircuitscapeRunner.run_batch, client_ctx, user_role, run_data, work_dir, storage_creds, multiuser, self.sess.log_str())
        return (None, False)


    def handle_run_verify(self, wsmsg):
        if self.sess.task != None:
            wsmsg.error("Your background task is still running. Wait for it to complete before starting another.")
            return (None, False)
        
        global SRVR_CFG
        wslogger = self._make_wslogger()
        user_role = self.sess.user_role() if SRVR_CFG.multiuser else 'standalone'
        
        data = wsmsg.nv['data']
        client_ctx = data['client_ctx']
        self.sess.task = CircuitscapeRunner(wslogger, wsmsg, CircuitscapeRunner.run_verify, client_ctx, user_role)
        return (None, False)


    def handle_logout(self, wsmsg):
        self.logout_or_detach()
        return ({}, True)

    def handle_file_list(self, wsmsg):
        filelist = [('..', True)]
        curdir = wsmsg.data('cwd', os.getcwd());
        newdir = wsmsg.data('dir')
        if newdir:
            curdir = os.path.normpath(os.path.join(curdir, newdir));
        for fname in os.listdir(curdir):
            full_fname = os.path.join(curdir, fname)
            is_dir = os.path.isdir(full_fname)
            #print (fname, is_dir)
            filelist.append((fname, is_dir))
        return ({'filelist': filelist, 'dir': curdir}, False)