def disconnect(self, message, id): # close threading print('disconnect') try: audit_log = Log.objects.get( channel=self.message.reply_channel.name) audit_log.is_finished = True audit_log.end_time = now() audit_log.save() cache_key = audit_log.gucamole_client_id client = GuacamoleClient( settings.GUACD_HOST, settings.GUACD_PORT) client.send_instruction(Instruction('select', cache_key)) instruction = client.read_instruction() kwargs = {'width': 1024, 'height': 768, 'read_only': 'true'} connection_args = [ kwargs.get(arg.replace('-', '_'), '') for arg in instruction.args ] client.send_instruction(Instruction('size', 1024, 768, 96)) client.send_instruction(Instruction('audio', *list())) client.send_instruction(Instruction('video', *list())) client.send_instruction(Instruction('image', *list())) client.send_instruction(Instruction('connect', *connection_args)) client.send_instruction(Instruction( 'disconnect', *connection_args)) except: pass finally: get_redis_instance().delete(id) self.message.reply_channel.send({"accept": False})
def post(self, request, key): if request.is_ajax(): channel_name = request.POST.get('channel_name', None) try: data = Log.objects.get(channel=channel_name) if data.is_finished: return JsonResponse({ 'status': False, 'message': 'Ssh terminal does not exist!' }) else: data.end_time = now() data.is_finished = True data.save() queue = get_redis_instance() redis_channel = queue.pubsub() if '_' in channel_name: queue.publish( channel_name.rsplit('_')[0], json.dumps(['close'])) else: queue.publish(channel_name, json.dumps(['close'])) return JsonResponse({ 'status': True, 'message': 'Terminal has been killed !' }) except ObjectDoesNotExist: return JsonResponse({ 'status': False, 'message': 'Request object does not exist!' })
def post(self, request): if not request.is_ajax(): conn = get_redis_instance() version = request.POST.get('version', None) protocol = request.POST.get('protocol', None) identify = request.POST.get('identify', None) if version and protocol in ["rdp", "ssh", "sftp"] and identify: identify_data = conn.get(identify) if isinstance(identify_data, bytes): identify_data = identify_data.decode() else: identify_data = identify_data if identify_data == 'ok' and version == __webterminalhelperversion__: conn.set(identify, 'installed') return JsonResponse({'status': True, 'message': 'ok'}) elif identify_data == 'ok' and version != __webterminalhelperversion__: conn.set(identify, 'need upgrade') return JsonResponse({'status': False, 'message': 'no'}) else: conn.delete(identify) # not install webterminal helper return JsonResponse({'status': False, 'message': 'no'}) else: return JsonResponse({ 'status': False, 'message': 'Method not allowed!' }) else: return JsonResponse({ 'status': False, 'message': 'Method not allowed!' })
def post(self, request): if request.is_ajax(): serverid = request.POST.get('serverid', None) try: data = ServerInfor.objects.get(id=serverid) username = uuid.uuid4().hex[0:5] password = uuid.uuid4().hex conn = get_redis_instance() encrypt = PyCrypt('88aaaf7ffe3c6c0488aaaf7ffe3c6c04') key = encrypt.encrypt(content=username + password) key = encrypt.md5_crypt(key) serverid = encrypt.encrypt(content=serverid) if data.credential.protocol not in ['rdp', 'vnc']: password = encrypt.encrypt(content=password) request_username = encrypt.encrypt( content=self.request.user.username) if isinstance(serverid, bytes): serverid = serverid.decode('utf8') if isinstance(request_username, bytes): request_username = request_username.decode('utf8') conn.set(key, '{0}_{1}'.format(serverid, request_username)) conn.set(username, password) conn.expire(key, 60) conn.expire(username, 60) if isinstance(password, bytes): password = password.decode('utf8') return JsonResponse({'status': True, 'message': {'username': username, 'password': password}}) except ObjectDoesNotExist: return JsonResponse({'status': False, 'message': 'Request object does not exist!'})
def close(self, status=True): """ Closes the WebSocket from the server end """ conn = get_redis_instance() conn.delete(self.kwargs.get("id", None)) self.message.reply_channel.send({"close": status})
def post(self, request): if request.is_ajax(): id = request.POST.get('id', None) try: log_object = Log.objects.get(id=id) queue = get_redis_instance() queue.pubsub() queue.publish(log_object.channel, '10.disconnect;') log_object.end_time = now() log_object.is_finished = True log_object.save() return JsonResponse({ 'status': True, 'message': 'Session has been killed !' }) except ObjectDoesNotExist: return JsonResponse({ 'status': False, 'message': 'Request object does not exist!' }) except Exception, e: log_object = Log.objects.get(id=id) log_object.end_time = now() log_object.is_finished = True log_object.save() return JsonResponse({'status': False, 'message': str(e)})
def post(self, request): if request.is_ajax(): conn = get_redis_instance() version = request.POST.get('version', None) protocol = request.POST.get('protocol', None) identify = request.POST.get('identify', None) if identify is not None and version is None and protocol is None: # get identify id id = str(uuid.uuid4()) conn.set(id, 'ok') conn.expire(id, 15) return JsonResponse({'status': True, 'message': id}) elif protocol in ["rdp", "ssh", "sftp"] and identify: if conn.get(identify) == 'installed': conn.delete(identify) return JsonResponse({'status': True, 'message': 'ok'}) elif conn.get(identify) == 'need upgrade': conn.delete(identify) return JsonResponse({'status': False, 'message': 'Webterminal helper need upgrade to version: {0}'.format(__webterminalhelperversion__)}) else: conn.delete(identify) # not install webterminal helper return JsonResponse({'status': False, 'message': 'no'}) else: return JsonResponse({'status': False, 'message': 'Method not allowed!'}) else: return JsonResponse({'status': False, 'message': 'Method not allowed!'})
def run(self): from webterminal.asgi import channel_layer with self.read_lock: while True: try: instruction = self.client.receive() if instruction: if instruction.startswith('bytearray(b'): instruction = instruction.rsplit( "bytearray(b'")[1].rsplit("')")[0] channel_layer.send(self.message.reply_channel.name, {"text": instruction}) # with open(os.path.join(self.recording_path,self.message.reply_channel.name),'ab+') as f: # f.write(instruction) else: break except timeout: queue = get_redis_instance() queue.pubsub() queue.publish(self.message.reply_channel.name, '10.disconnect;') # End-of-instruction marker channel_layer.send(self.message.reply_channel.name, {"text": '0.;'})
def redis_queue(self): redis_instance = get_redis_instance() redis_sub = redis_instance.pubsub() if self.elementid: redis_sub.subscribe(self.elementid.rsplit('_')[0]) else: redis_sub.subscribe(self.message.reply_channel.name) return redis_sub
def dispatch(self, request, *args, **kwargs): if "key" not in kwargs.keys(): raise PermissionDenied('403 Forbidden') conn = get_redis_instance() login_info = conn.get(kwargs["key"]) if login_info: try: login_info = json.loads(login_info) self.request.user = login_info.get("nickname", "Anonymous") except: raise PermissionDenied('403 Forbidden') else: raise PermissionDenied('403 Forbidden') return super(CommandLogList, self).dispatch(request, *args, **kwargs)
def post(self, request): if request.is_ajax(): channel_name = request.POST.get('channel_name', None) try: data = Log.objects.get(channel=channel_name) if request.user.username == data.user.username or request.user.has_perm( 'common.can_kill_serverinfo'): if data.is_finished: return JsonResponse({ 'status': False, 'message': 'Ssh terminal does not exist!' }) else: data.end_time = now() data.is_finished = True data.save() queue = get_redis_instance() redis_channel = queue.pubsub() if '_' in channel_name: queue.publish( channel_name.rsplit('_')[0], json.dumps(['close'])) else: queue.publish(channel_name, json.dumps(['close'])) return JsonResponse({ 'status': True, 'message': 'Terminal has been killed !' }) else: return JsonResponse({ 'status': False, 'message': 'You do not have permission to kill active user action !' }) except ObjectDoesNotExist: return JsonResponse({ 'status': False, 'message': 'Request object does not exist!' })
def post(self, request): data = self.request.POST.get("data", None) if not data: try: data = json.loads(request.body) if isinstance(data, str): data = ast.literal_eval(data) data = data.get("data", None) except: pass if data: try: endeins = EnDeCrypt() data = ast.literal_eval(endeins.decrypt(data)) temp_key = uuid.uuid4().hex cache_data = { "nickname": data.get("nickname"), "ip": data.get("ip"), "port": data.get("port"), "public_ip": data.get("public_ip", None), "private_ip": data.get("private_ip", None), "admin_user": data.get("admin_user"), "system_user": data.get("system_user"), "user_key": data.get("user_key"), "password": data.get("password", "") } # get redis connection conn = get_redis_instance() conn.set(temp_key, json.dumps(cache_data)) conn.expire(temp_key, 60) return JsonResponse({ 'status': True, 'message': 'Success!', "key": temp_key }) except Exception as e: print(traceback.print_exc()) return JsonResponse({ 'status': False, 'message': 'Illegal request or data!', "data": data }) return JsonResponse({ 'status': False, 'message': 'Illegal request or data!' })
def check_auth_password(self, username, password): conn = get_redis_instance() encrypt = PyCrypt('88aaaf7ffe3c6c0488aaaf7ffe3c6c04') if password == '' or password == u'': return paramiko.AUTH_FAILED try: key = encrypt.encrypt(content=username + encrypt.decrypt(password)) key = encrypt.md5_crypt(key) except: conn.delete(username) return paramiko.AUTH_FAILED serverid = conn.get(key) if serverid is None: conn.delete(username) conn.delete(key) return paramiko.AUTH_FAILED else: try: if isinstance(serverid, bytes): serverid = serverid.decode('utf8', 'ignore') serverid, request_username = serverid.rsplit('_') serverid = encrypt.decrypt(serverid) request_username = encrypt.decrypt(request_username) self.request_http_username = request_username try: User.objects.get(username=request_username) except ObjectDoesNotExist: print('request user name not exist') conn.delete(username) conn.delete(key) return paramiko.AUTH_FAILED except: print('user {0} auth failed'.format(username)) conn.delete(username) conn.delete(key) return paramiko.AUTH_FAILED try: ServerInfor.objects.get(id=serverid) self.serverid = int(serverid) except ObjectDoesNotExist: conn.delete(username) conn.delete(key) return paramiko.AUTH_FAILED if isinstance(conn.get(username), bytes) and isinstance(password, str): password = password.encode('utf8', 'ignore') try: if conn.get(username) is not None and password == conn.get( username) and serverid != None: print('success connect to webterminal server') conn.delete(username) conn.delete(key) return paramiko.AUTH_SUCCESSFUL except: conn.delete(username) conn.delete(key) return paramiko.AUTH_FAILED conn.delete(username) conn.delete(key) return paramiko.AUTH_FAILED
def posix_shell(chan, channel, channelid): stdout = list() begin_time = time.time() last_write_time = {'last_activity_time': begin_time} command = list() logobj = Log.objects.get(log=channelid) vim_flag = False vim_data = '' try: directory_date_time = timezone.now() log_name = os.path.join( '{0}-{1}-{2}'.format(directory_date_time.year, directory_date_time.month, directory_date_time.day), '{0}'.format(channelid)) from webterminal.asgi import channel_layer # terminate ssh session control redis_instance = get_redis_instance() redis_sub = redis_instance.pubsub() redis_sub.subscribe(logobj.channel) while True: text = redis_sub.get_message() if text: try: if isinstance(text['data'], bytes): text['data'] = smart_unicode(text['data']) data = json.loads(text['data']) except: data = [] if len(data) >= 1 and str(data[0]) == 'close': if not channel.closed: channel.close() r, w, x = select.select([channel], [], []) if channel in r: data = channel.recv(1024 * 24) if len(data) == 0: if not channel.closed: channel.send('\r\n*** EOF\r\n') break if data == "exit\r\n" or data == "logout\r\n" or data == 'logout': channel.close() now = time.time() delay = now - last_write_time['last_activity_time'] last_write_time['last_activity_time'] = now if vim_flag: vim_data += data if '\r' not in smart_unicode(data): command.append(smart_unicode(data)) else: command_result = CommandDeal().deal_command( ''.join(command)) if len(command_result) != 0: # vim command record patch if command_result.strip().startswith( 'vi') or command_result.strip().startswith( 'fg'): CommandLog.objects.create( log=logobj, command=command_result[0:255]) vim_flag = True else: if vim_flag: if re.compile('\[.*@.*\][\$#]').search( vim_data): vim_flag = False vim_data = '' else: CommandLog.objects.create( log=logobj, command=command_result[0:255]) command = list() if isinstance(data, unicode): stdout.append([delay, data]) else: stdout.append([ delay, codecs.getincrementaldecoder('UTF-8')( 'replace').decode(data) ]) channel_layer.send_group( smart_unicode('monitor-{0}'.format(channelid)), {'text': json.dumps(['stdout', smart_unicode(data)])}) if not chan.closed: chan.send(data) else: print('else') finally: attrs = { "version": 1, "width": 180, "height": 40, "duration": round(time.time() - begin_time, 6), "command": os.environ.get('SHELL', None), 'title': None, "env": { "TERM": os.environ.get('TERM'), "SHELL": os.environ.get('SHELL', 'sh') }, 'stdout': list(map(lambda frame: [round(frame[0], 6), frame[1]], stdout)) } mkdir_p('/'.join(os.path.join(MEDIA_ROOT, log_name).rsplit('/')[0:-1])) with open(os.path.join(MEDIA_ROOT, log_name), "a") as f: f.write( json.dumps(attrs, ensure_ascii=True, cls=CustomeFloatEncoder, indent=2)) logobj.is_finished = True logobj.end_time = timezone.now() logobj.save() chan.close() channel.close()
def receive(self, text=None, bytes=None, **kwargs): self.ip = self.kwargs.get("ip", None) self.id = self.kwargs.get("id", None) try: if text: data = json.loads(text) begin_time = time.time() if isinstance(data, list) and data[0] == 'ip' and len(data) == 5: # get auth info from cache conn = get_redis_instance() authinfo = conn.get(self.id) # handle auth info try: authinfo = json.loads(authinfo) # auth server ssh username username = authinfo.get("system_user") password = authinfo.get("password", "") if len(password) >0: method = "password" else: method = "key" key = authinfo.get("user_key") port = authinfo.get("port") loginuser = authinfo.get("nickname") # auth user except: self.message.reply_channel.send( {"text": '\033[1;3;31mHandle auth info encountered a error,Please contact your administrator!\033[0m'}, immediately=True) self.message.reply_channel.send({"accept": False}) self.close() return ip = data[1] width = data[2] height = data[3] id = data[4] self.ssh.set_missing_host_key_policy( paramiko.AutoAddPolicy()) # permission control # self.message.reply_channel.send( # {"text": '\033[1;3;31mYou have not permission to connect server {0}!\033[0m'.format(ip)}, immediately=True) #self.message.reply_channel.send({"accept": False}) #logger.error("{0} have not permission to connect server {1}!".format(self.message.user.username, ip)) # return try: if method == 'password': self.ssh.connect( ip, port=port, username=username, password=password, timeout=3) else: private_key = StringIO(key) if 'RSA' in key: private_key = paramiko.RSAKey.from_private_key( private_key) elif 'DSA' in key: private_key = paramiko.DSSKey.from_private_key( private_key) elif 'EC' in key: private_key = paramiko.ECDSAKey.from_private_key( private_key) elif 'OPENSSH' in key: private_key = paramiko.Ed25519Key.from_private_key( private_key) else: self.message.reply_channel.send({"text": '\033[1;3;31munknown or unsupported key type, only support rsa dsa ed25519 ecdsa key type\033[0m'}, immediately=True) self.message.reply_channel.send( {"accept": False}) logger.error( "unknown or unsupported key type, only support rsa dsa ed25519 ecdsa key type!") self.ssh.connect( ip, port=port, username=username, pkey=private_key, timeout=3) # when connect server sucess record log audit_log = Log.objects.create( user=username, loginuser=loginuser, server=ip, channel=self.message.reply_channel.name, width=width, height=height) audit_log.save() except socket.timeout: self.message.reply_channel.send( {"text": '\033[1;3;31mConnect to server time out\033[0m'}, immediately=True) logger.error( "Connect to server {0} time out!".format(ip)) self.message.reply_channel.send({"accept": False}) return except Exception as e: self.message.reply_channel.send( {"text": '\033[1;3;31mCan not connect to server: {0}\033[0m'.format(e)}, immediately=True) self.message.reply_channel.send({"accept": False}) logger.error( "Can not connect to server {0}: {1}".format(ip, e)) return chan = self.ssh.invoke_shell( width=width, height=height, term='xterm') # open a new threading to handle ssh to avoid global variable bug sshterminal = SshTerminalThread(self.message, chan) sshterminal.setDaemon = True sshterminal.start() directory_date_time = now() log_name = os.path.join('{0}-{1}-{2}'.format(directory_date_time.year, directory_date_time.month, directory_date_time.day), '{0}'.format(audit_log.log)) # open ssh terminal interactivessh = InterActiveShellThread( chan, self.message.reply_channel.name, log_name=log_name, width=width, height=height) interactivessh.setDaemon = True interactivessh.start() elif isinstance(data, list) and data[0] in ['stdin', 'stdout']: self.queue.publish( self.message.reply_channel.name, json.loads(text)[1]) elif isinstance(data, list) and data[0] == u'set_size': self.queue.publish(self.message.reply_channel.name, text) elif isinstance(data, list) and data[0] == u'close': self.disconnect(self.message) return else: self.queue.publish(self.message.reply_channel.name, text) logger.error("Unknow command found!") elif bytes: self.queue.publish( self.message.reply_channel.name, bytes) except socket.error: audit_log = Log.objects.get( channel=self.message.reply_channel.name) audit_log.is_finished = True audit_log.end_time = now() audit_log.save() self.closessh() self.close() except ValueError: self.queue.publish( self.message.reply_channel.name, smart_unicode(text)) except Exception as e: logger.error(traceback.print_exc()) self.closessh() self.close()
def posix_shell(chan, channel, log_name=None, width=90, height=40, elementid=None): from webterminal.asgi import channel_layer stdout = list() begin_time = time.time() last_write_time = {'last_activity_time': begin_time} command = list() if elementid: logobj = Log.objects.get(channel=elementid) else: logobj = Log.objects.get(channel=channel) vim_flag = False vim_data = '' try: chan.settimeout(0.0) while True: try: x = u(chan.recv(1024)) if len(x) == 0: if elementid: channel_layer.send( channel, { 'text': json.dumps([ 'disconnect', smart_unicode('\r\n*** EOF\r\n'), elementid.rsplit('_')[0] ]) }) else: channel_layer.send( channel, { 'text': json.dumps([ 'disconnect', smart_unicode('\r\n*** EOF\r\n') ]) }) break now = time.time() delay = now - last_write_time['last_activity_time'] last_write_time['last_activity_time'] = now if x == "exit\r\n" or x == "logout\r\n" or x == 'logout': chan.close() else: if vim_flag: vim_data += x logger.debug('raw data {0}'.format(command)) if '\r\n' not in x: command.append(x) else: command = CommandDeal().deal_command(''.join(command)) if len(command) != 0: #vim command record patch logger.debug('command {0}'.format(command)) if command.strip().startswith( 'vi') or command.strip().startswith('fg'): CommandLog.objects.create(log=logobj, command=command) vim_flag = True else: if vim_flag: if re.compile('\[.*@.*\][\$#]').search( vim_data): vim_flag = False vim_data = '' else: CommandLog.objects.create(log=logobj, command=command) command = list() if isinstance(x, unicode): stdout.append([delay, x]) else: stdout.append([ delay, codecs.getincrementaldecoder('UTF-8')( 'replace').decode(x) ]) if isinstance(x, unicode): if elementid: channel_layer.send( channel, { 'text': json.dumps( ['stdout', x, elementid.rsplit('_')[0]]) }) else: channel_layer.send(channel, {'text': json.dumps(['stdout', x])}) else: if elementid: channel_layer.send( channel, { 'text': json.dumps([ 'stdout', smart_unicode(x), elementid.rsplit('_')[0] ]) }) else: channel_layer.send( channel, {'text': json.dumps(['stdout', smart_unicode(x)])}) #send message to monitor group if log_name: channel_layer.send_group( u'monitor-{0}'.format(log_name.rsplit('/')[1]), {'text': json.dumps(['stdout', smart_unicode(x)])}) except socket.timeout: pass except Exception, e: logger.error(traceback.print_exc()) if elementid: channel_layer.send( channel, { 'text': json.dumps([ 'stdout', 'A bug find,You can report it to me' + smart_unicode(e), elementid.rsplit('_')[0] ]) }) else: channel_layer.send( channel, { 'text': json.dumps([ 'stdout', 'A bug find,You can report it to me' + smart_unicode(e) ]) }) finally: attrs = { "version": 1, "width": width, #int(subprocess.check_output(['tput', 'cols'])), "height": height, #int(subprocess.check_output(['tput', 'lines'])), "duration": round(time.time() - begin_time, 6), "command": os.environ.get('SHELL', None), 'title': None, "env": { "TERM": os.environ.get('TERM'), "SHELL": os.environ.get('SHELL', 'sh') }, 'stdout': list(map(lambda frame: [round(frame[0], 6), frame[1]], stdout)) } mkdir_p('/'.join(os.path.join(MEDIA_ROOT, log_name).rsplit('/')[0:-1])) with open(os.path.join(MEDIA_ROOT, log_name), "a") as f: f.write( json.dumps(attrs, ensure_ascii=True, cls=CustomeFloatEncoder, indent=2)) if elementid: audit_log = Log.objects.get(channel=elementid, log=log_name.rsplit('/')[-1]) else: audit_log = Log.objects.get(channel=channel, log=log_name.rsplit('/')[-1]) audit_log.is_finished = True audit_log.end_time = timezone.now() audit_log.save() #hand ssh terminal exit queue = get_redis_instance() redis_channel = queue.pubsub() queue.publish(channel, json.dumps(['close']))
def get(self, request, id): token = '{0}{1}'.format(''.join(str(uuid.uuid4()).rsplit('-')), id) conn = get_redis_instance() conn.set(token, request.user.username) return render_to_response('guacamole/index.html', locals())
def queue(self): queue = get_redis_instance() channel = queue.pubsub() return queue
def authenticate(self, id): if get_redis_instance().get(id) != None: return True else: return False
def connect(self, message, id): self.message.reply_channel.send({"accept": True}) user = get_redis_instance().get(id) if not self.authenticate(id): self.message.reply_channel.send({"text": json.dumps( {'status': False, 'message': 'You must login to the system!'})}, immediately=True) self.message.reply_channel.send({"accept": False}) else: # permission auth username = get_redis_instance().get(id) try: Permission.objects.get( user__username=username, groups__servers__id=int(id[-1])) except ObjectDoesNotExist: self.message.reply_channel.send({"text": json.dumps( '\033[1;3;31mYou have not permission to connect server !\033[0m')}, immediately=True) self.message.reply_channel.send({"accept": False}) return except MultipleObjectsReturned: pass client = GuacamoleClient( settings.GUACD_HOST, settings.GUACD_PORT) try: data = ServerInfor.objects.get(id=int(id[-1])) if data.credential.protocol in ['vnc', 'rdp', 'telnet']: pass else: self.message.reply_channel.send({"accept": False}) except ObjectDoesNotExist: # server info not exist self.message.reply_channel.send({"accept": False}) cache_key = str(uuid.uuid4()) directory_date_time = now() recording_path = os.path.join(MEDIA_ROOT, '{0}-{1}-{2}'.format( directory_date_time.year, directory_date_time.month, directory_date_time.day)) if isinstance(username, bytes): username = username.decode() drive_path = os.path.join(MEDIA_ROOT, str(username), 'Download') """ Create recording media file and drive path """ mkdir_p(recording_path) mkdir_p(drive_path) try: client.handshake(width=data.credential.width, height=data.credential.height, protocol=data.credential.protocol, hostname=data.ip, port=data.credential.port, username=data.credential.username, password=data.credential.password, recording_path=recording_path, recording_name=cache_key, create_recording_path='true', enable_wallpaper='true', ignore_cert='true', enable_drive='true', drive_path=drive_path, create_drive_path='true', security=data.credential.security, # console_audio='true', # enable_audio_input='true', # disable_audio='false', # console='true', enable_full_window_drag='true', resize_method="reconnect" # display-update ) except Exception as e: print(e) print(traceback.print_exc()) self.message.reply_channel.send({"accept": False}) return self.message.reply_channel.send( {"text": '0.,{0}.{1};'.format(len(cache_key), cache_key)}, immediately=True) audit_log = Log.objects.create(user=User.objects.get(username=username), server=data, channel=self.message.reply_channel.name, width=data.credential.width, height=data.credential.height, log=cache_key, gucamole_client_id=client._id) audit_log.save() guacamolethread = GuacamoleThread(self.message, client) guacamolethread.setDaemon = True guacamolethread.start() guacamolethreadwrite = GuacamoleThreadWrite(self.message, client) guacamolethreadwrite.setDaemon = True guacamolethreadwrite.start()
def redis_queue(self): redis_instance = get_redis_instance() redis_sub = redis_instance.pubsub() redis_sub.subscribe(self.message.reply_channel.name) return redis_sub