后端:django;websocket;多线程;前端:xterm;其他:k8s
库:
from dwebsocket.decorators import accept_websocket
from kubernetes.stream import stream
后台处理:
ws.read()与ssh.send()绑定在同一线程;
ws.send()与ssh.read()绑定在同一线程
@accept_websocket
def pod_exec(request):
if request.is_websocket():
namespace = 'dev-namespace'
pod = "demo0908-857f66466f-l9566"
container = "demo0908"
api_instance = kube.corevaapi
exec_command = [
"/bin/sh",
"-c",
'TERM=xterm-256color; export TERM; [ -x /bin/bash ] '
'&& ([ -x /usr/bin/script ] '
'&& /usr/bin/script -q -c "/bin/bash" /dev/null || exec /bin/bash) '
'|| exec /bin/sh']
container_stream = stream(api_instance.connect_get_namespaced_pod_exec,
name=pod,
namespace=namespace,
container=container,
command=exec_command,
stderr=True, stdin=True,
stdout=True, tty=True,
_preload_content=False
)
commands = [
"echo This message goes to stdout",
"echo \"This message goes to stderr\" >&2",
]
kub_stream = K8SStreamThread(request.websocket, container_stream)
kub_stream.start()
while container_stream.is_open() and not request.websocket.is_closed():
ws_reviced = request.websocket.read()
if (ws_reviced != None):
# container_stream.write_stdin('exit\r')
re = container_stream.write_stdin(str(ws_reviced, encoding="utf-8"))
else:
if not request.websocket.is_closed():
request.websocket.close()
if container_stream.is_open():
container_stream.close()
else:
return JsonResponse({"msg": "use websocket connect"})
class K8SStreamThread(Thread):
def __init__(self, websocket, container_stream):
Thread.__init__(self)
self.websocket = websocket
self.stream = container_stream
def run(self):
while self.stream.is_open() and not self.websocket.is_closed():
# self.stream.update()
if self.stream.peek_stdout():
stdout = self.stream.read_stdout()
#stdout = self.stream.peek_stdout()
if stdout:
self.websocket.send(stdout.encode(encoding='utf-8'))
if self.stream.peek_stderr():
stderr = self.stream.read_stderr()
self.websocket.send(stderr)
else:
if not self.websocket.is_closed():
self.websocket.close()
if self.stream.is_open():
self.stream.close()
依赖:term或xterm插件
var term;
//var wsUrl = "ws://127.0.0.1:8080/server";
var wsUrl = "ws://127.0.0.1:8000/api/kube/podexec/";
websocket = new WebSocket(wsUrl);//new 一个websocket实例
websocket.onopen = function (evt) {//打开连接websocket
term = new Terminal({ //new 一个terminal实例,就是数据展示的屏幕和一些见简单设置,包括屏幕的宽度,高度,光标是否闪烁等等
cols: 200,
rows: 80,
screenKeys: true,
useStyle: true,
cursorBlink: true,
});
/*term实时监控输入的数据,并且websocket把实时数据发送给后台*/
term.on('data', function (data) {//term.on方法就是实时监控输入的字段,
websocket.send(data);//websocket发送给后台
});
term.on('title', function (title) {
document.title = 'test-jump';
});
term.open(document.getElementById('container-terminal'));//屏幕将要在哪里展示,就是屏幕展示的地方
websocket.onmessage = function (evt) {//接受到数据
term.write(evt.data);//把接收的数据写到这个插件的屏幕上
}
websocket.onclose = function (evt) {//websocket关闭
term.write("Session terminated");
term.destroy();//屏幕关闭
}
websocket.onerror = function (evt) {//失败额处理
if (typeof console.log == "function") {
console.log(evt)
}
}
}
var close = function () {//关闭websocket
websocket.close();
};
1.websocket与k8s.stream连接是否正常的判断与断开连接的条件,处理不好后台会残留线程
2.ssh返回中部分字符看似乱码,实则为ssh样式(颜色)显示,需配合term调试才能显示实际效果
3.k8s stream接口中peek_stdout()与read_stdout()区别