jumpserver/run_websocket.py

225 lines
6.5 KiB
Python
Raw Normal View History

2015-11-02 03:18:06 +00:00
# coding: utf-8
import time
import json
2015-11-02 15:20:40 +00:00
import os
import sys
2015-11-02 03:18:06 +00:00
import os.path
2015-11-03 15:03:31 +00:00
import threading
2015-11-02 03:18:06 +00:00
import tornado.ioloop
import tornado.options
import tornado.web
import tornado.websocket
import tornado.httpserver
2015-11-03 11:12:15 +00:00
import tornado.gen
2015-11-03 15:03:31 +00:00
from tornado.websocket import WebSocketClosedError
2015-11-02 03:18:06 +00:00
from tornado.options import define, options
2015-11-05 12:07:21 +00:00
from pyinotify import WatchManager, Notifier, ProcessEvent, IN_DELETE, IN_CREATE, IN_MODIFY, AsyncNotifier
2015-11-05 10:31:00 +00:00
2015-11-05 12:07:21 +00:00
# from gevent import monkey
# monkey.patch_all()
# import gevent
2015-11-05 10:31:00 +00:00
from gevent.socket import wait_read, wait_write
import paramiko
try:
import simplejson as json
except ImportError:
import json
2015-11-02 03:18:06 +00:00
2015-11-05 12:07:21 +00:00
define("port", default=3000, help="run on the given port", type=int)
2015-11-03 11:12:15 +00:00
define("host", default='0.0.0.0', help="run port on", type=str)
2015-11-02 03:18:06 +00:00
2015-11-03 15:21:33 +00:00
class MyThread(threading.Thread):
def __init__(self, *args, **kwargs):
super(MyThread, self).__init__(*args, **kwargs)
def run(self):
try:
super(MyThread, self).run()
except WebSocketClosedError:
pass
2015-11-02 15:20:40 +00:00
class EventHandler(ProcessEvent):
def __init__(self, client=None):
self.client = client
def process_IN_CREATE(self, event):
print "Create file:%s." % os.path.join(event.path, event.name)
def process_IN_DELETE(self, event):
print "Delete file:%s." % os.path.join(event.path, event.name)
def process_IN_MODIFY(self, event):
print "Modify file:%s." % os.path.join(event.path, event.name)
2015-11-03 15:21:33 +00:00
self.client.write_message(f.read())
2015-11-02 15:20:40 +00:00
def file_monitor(path='.', client=None):
wm = WatchManager()
mask = IN_DELETE | IN_CREATE | IN_MODIFY
2015-11-03 15:03:31 +00:00
notifier = AsyncNotifier(wm, EventHandler(client))
2015-11-02 15:20:40 +00:00
wm.add_watch(path, mask, auto_add=True, rec=True)
if not os.path.isfile(path):
print "You should monitor a file"
sys.exit(3)
else:
2015-11-05 12:07:21 +00:00
print "now starting monitor %s." % path
2015-11-02 15:20:40 +00:00
global f
f = open(path, 'r')
st_size = os.stat(path)[6]
f.seek(st_size)
while True:
try:
notifier.process_events()
if notifier.check_events():
notifier.read_events()
except KeyboardInterrupt:
print "keyboard Interrupt."
notifier.stop()
break
2015-11-02 03:18:06 +00:00
class Application(tornado.web.Application):
def __init__(self):
handlers = [
2015-11-03 11:12:15 +00:00
(r'/monitor', MonitorHandler),
2015-11-05 10:31:00 +00:00
(r'/terminal', WebTerminalHandler),
2015-11-02 03:18:06 +00:00
]
setting = {
'cookie_secret': 'DFksdfsasdfkasdfFKwlwfsdfsa1204mx',
'template_path': os.path.join(os.path.dirname(__file__), 'templates'),
'static_path': os.path.join(os.path.dirname(__file__), 'static'),
2015-11-03 15:03:31 +00:00
'debug': True,
2015-11-02 03:18:06 +00:00
}
tornado.web.Application.__init__(self, handlers, **setting)
2015-11-03 11:12:15 +00:00
class MonitorHandler(tornado.websocket.WebSocketHandler):
2015-11-03 15:03:31 +00:00
clients = []
threads = []
2015-11-02 03:18:06 +00:00
2015-11-03 11:12:15 +00:00
def __init__(self, *args, **kwargs):
self.file_path = None
super(self.__class__, self).__init__(*args, **kwargs)
2015-11-02 15:20:40 +00:00
def check_origin(self, origin):
return True
2015-11-02 03:18:06 +00:00
def open(self):
2015-11-03 11:12:15 +00:00
# 获取监控的path
self.file_path = self.get_argument('file_path', '')
2015-11-03 15:03:31 +00:00
MonitorHandler.clients.append(self)
2015-11-03 15:21:33 +00:00
thread = MyThread(target=file_monitor, args=('%s.log' % self.file_path, self))
2015-11-03 15:03:31 +00:00
MonitorHandler.threads.append(thread)
2015-11-02 03:18:06 +00:00
self.stream.set_nodelay(True)
2015-11-03 15:03:31 +00:00
print len(MonitorHandler.threads), len(MonitorHandler.clients)
2015-11-02 03:18:06 +00:00
def on_message(self, message):
2015-11-03 11:12:15 +00:00
self.write_message('Connect WebSocket Success. <br/>')
# 监控日志,发生变动发向客户端
2015-11-03 15:03:31 +00:00
try:
for t in MonitorHandler.threads:
if t.is_alive():
continue
t.setDaemon(True)
t.start()
2015-11-03 15:21:33 +00:00
except WebSocketClosedError:
2015-11-03 15:03:31 +00:00
client_index = MonitorHandler.clients.index(self)
MonitorHandler.threads[client_index].stop()
MonitorHandler.clients.remove(self)
MonitorHandler.threads.remove(MonitorHandler.threads[client_index])
2015-11-02 15:20:40 +00:00
2015-11-02 03:18:06 +00:00
def on_close(self):
# 客户端主动关闭
2015-11-03 15:03:31 +00:00
# self.close()
print "Close websocket."
client_index = MonitorHandler.clients.index(self)
2015-11-03 11:12:15 +00:00
MonitorHandler.clients.remove(self)
2015-11-03 15:03:31 +00:00
MonitorHandler.threads.remove(MonitorHandler.threads[client_index])
2015-11-02 03:18:06 +00:00
2015-11-05 10:31:00 +00:00
class WebTerminalHandler(tornado.websocket.WebSocketHandler):
tasks = []
def __init__(self, *args, **kwargs):
self.chan = None
self.ssh = None
super(WebTerminalHandler, self).__init__(*args, **kwargs)
def check_origin(self, origin):
return True
def open(self):
self.ssh = paramiko.SSHClient()
self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
self.ssh.connect('127.0.0.1', 22, 'root', 'redhat')
except:
self.write_message(json.loads({'data': 'Connect server Error'}))
self.close()
self.chan = self.ssh.invoke_shell(term='xterm')
WebTerminalHandler.tasks.append(threading.Thread(target=self._forward_outbound))
for t in WebTerminalHandler.tasks:
if t.is_alive():
continue
t.setDaemon(True)
t.start()
def on_message(self, message):
data = json.loads(message)
if not data:
return
if 'resize' in data:
self.chan.resize_pty(
data['resize'].get('width', 80),
data['resize'].get('height', 24))
if 'data' in data:
self.chan.send(data['data'])
def on_close(self):
self.write_message(json.dumps({'data': 'close websocket'}))
def _forward_outbound(self):
""" Forward outbound traffic (ssh -> websockets) """
try:
data = ''
while True:
wait_read(self.chan.fileno())
recv = self.chan.recv(1024)
if not len(recv):
return
data += recv
try:
self.write_message(json.dumps({'data': data}))
data = ''
except UnicodeDecodeError:
pass
finally:
self.close()
2015-11-02 03:18:06 +00:00
if __name__ == '__main__':
tornado.options.parse_command_line()
app = Application()
server = tornado.httpserver.HTTPServer(app)
2015-11-03 11:12:15 +00:00
server.bind(options.port, options.host)
# server.listen(options.port)
server.start(num_processes=1)
2015-11-02 03:18:06 +00:00
tornado.ioloop.IOLoop.instance().start()