parent
8d5732df9d
commit
8ed2e800f6
|
@ -30,9 +30,9 @@ class HostModel(BaseModel):
|
|||
def __str__(self):
|
||||
return f'主机:{self.hostname}'
|
||||
|
||||
def get_host_client(self, pkey=None, default_env=None):
|
||||
def get_host_client(self, pkey=None):
|
||||
pkey = pkey or self.private_key
|
||||
return SSH(hostname=self.ip, port=self.port, username=self.username, pkey=pkey, default_env=default_env)
|
||||
return SSH(hostname=self.ip, port=self.port, username=self.username, pkey=pkey)
|
||||
|
||||
|
||||
class HostType(BaseModel):
|
||||
|
|
|
@ -20,7 +20,6 @@ class BaseConstant:
|
|||
SERVER_IP = get_ip_address()
|
||||
BASE_DIR = Path(__file__).resolve().parent.parent
|
||||
DEBUG = True
|
||||
DEFAULT_CACHE_REDIS = "redis://127.0.0.1:6379/1"
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.mysql', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
|
||||
|
|
|
@ -4,7 +4,6 @@ from threading import Thread
|
|||
|
||||
from channels.generic.websocket import WebsocketConsumer
|
||||
from channels.exceptions import StopConsumer
|
||||
from django.contrib.auth.models import AnonymousUser
|
||||
from django_redis import get_redis_connection
|
||||
|
||||
from apps.host.models import HostModel
|
||||
|
@ -30,7 +29,7 @@ class SshConsumer(WebsocketConsumer):
|
|||
self.user = self.scope['user']
|
||||
self.host_id = self.scope['url_route']['kwargs']['id']
|
||||
|
||||
if isinstance(self.user, AnonymousUser):
|
||||
if not self.user:
|
||||
self.close()
|
||||
else:
|
||||
self.accept()
|
||||
|
@ -65,12 +64,7 @@ class SshConsumer(WebsocketConsumer):
|
|||
def receive(self, text_data=None, bytes_data=None):
|
||||
data = text_data or bytes_data
|
||||
if data:
|
||||
data = json.loads(data)
|
||||
resize = data.get('resize')
|
||||
if resize and len(resize) == 2:
|
||||
self.xterm.resize_pty(*resize)
|
||||
else:
|
||||
self.xterm.send(data['data'])
|
||||
self.xterm.send(data)
|
||||
|
||||
def websocket_disconnect(self, message):
|
||||
raise StopConsumer()
|
|
@ -43,8 +43,7 @@ class SshJob:
|
|||
service_post_name = service_name + '_post'
|
||||
service_post_path = os.path.join(SCRIPTS_DIR, service_post_name)
|
||||
if os.path.exists(service_post_path):
|
||||
print(type(result))
|
||||
command = "%s '%s'" % (service_post_path, json.dumps(result))
|
||||
command = "%s '%s'" % (service_post_path, result)
|
||||
output = os.popen(command)
|
||||
result = ast.literal_eval(output.read())
|
||||
update_job(instance=self.job, status="Success", result=result, host_by=host_ips)
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import logging
|
||||
|
||||
from channels.db import database_sync_to_async
|
||||
from django.contrib.auth.models import AnonymousUser
|
||||
|
||||
from apps.accounts.models import User
|
||||
from rest_framework_jwt.settings import api_settings
|
||||
|
@ -17,7 +16,7 @@ def get_user(user_id: int):
|
|||
try:
|
||||
user = User.objects.get(id=user_id)
|
||||
except User.DoesNotExist:
|
||||
return AnonymousUser()
|
||||
return None
|
||||
return user
|
||||
|
||||
|
||||
|
@ -34,11 +33,11 @@ class AuthMiddleware:
|
|||
user_id = None
|
||||
token = scope.get('query_string', None)
|
||||
if not token:
|
||||
scope['user'] = AnonymousUser()
|
||||
scope['user'] = None
|
||||
if token.decode().startswith('user_id='):
|
||||
user_id = token.decode().replace('user_id=', '')
|
||||
if not user_id:
|
||||
scope['user'] = AnonymousUser()
|
||||
scope['user'] = None
|
||||
else:
|
||||
scope['user'] = await get_user(user_id=user_id)
|
||||
return await self.application(scope, receive, send, *args, **kwargs)
|
||||
|
|
|
@ -5,7 +5,6 @@ from .middleware import AuthMiddleware
|
|||
|
||||
ws_router = AuthMiddleware(
|
||||
URLRouter([
|
||||
path('ws/exec/<str:token>/', ExecConsumer.as_asgi()),
|
||||
path('ws/ssh/<int:id>/', SshConsumer.as_asgi()),
|
||||
])
|
||||
)
|
||||
|
|
|
@ -8,9 +8,19 @@ https://docs.djangoproject.com/en/3.2/howto/deployment/asgi/
|
|||
"""
|
||||
|
||||
import os
|
||||
|
||||
from django.urls import path
|
||||
from channels.routing import ProtocolTypeRouter, URLRouter
|
||||
from django.core.asgi import get_asgi_application
|
||||
from consumer.consumers import SshConsumer
|
||||
from consumer.middleware import AuthMiddleware
|
||||
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'sysom.settings')
|
||||
|
||||
application = get_asgi_application()
|
||||
application = ProtocolTypeRouter({
|
||||
"http": get_asgi_application(),
|
||||
"websocket": AuthMiddleware(
|
||||
URLRouter([
|
||||
path('ws/ssh/<int:id>/', SshConsumer.as_asgi()),
|
||||
])
|
||||
)
|
||||
})
|
||||
|
|
|
@ -48,17 +48,6 @@ DEBUG = constant.DEBUG
|
|||
if DEBUG:
|
||||
CORS_ORIGIN_ALLOW_ALL = True
|
||||
|
||||
# Redis缓存
|
||||
CACHES = {
|
||||
"default": {
|
||||
"BACKEND": "django_redis.cache.RedisCache",
|
||||
"LOCATION": constant.DEFAULT_CACHE_REDIS,
|
||||
"OPTIONS": {
|
||||
"CLIENT_CLASS": "django_redis.client.DefaultClient",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Mysql数据库
|
||||
DATABASES = constant.DATABASES
|
||||
|
||||
|
@ -75,16 +64,6 @@ TEMPLATES = [
|
|||
WSGI_APPLICATION = 'sysom.wsgi.application'
|
||||
ASGI_APPLICATION = 'sysom.asgi.application'
|
||||
|
||||
# channels 配置
|
||||
CHANNEL_LAYERS = {
|
||||
"default": {
|
||||
"BACKEND": "channels_redis.core.RedisChannelLayer",
|
||||
"CONFIG": {
|
||||
"hosts": [("127.0.0.1", 6379)]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
||||
|
||||
LANGUAGE_CODE = constant.LANGUAGE_CODE
|
||||
|
|
|
@ -74,6 +74,11 @@ export default [
|
|||
name: 'match',
|
||||
component: './vmcore/match',
|
||||
},
|
||||
{
|
||||
path: '/vmcore/analyse',
|
||||
name: 'analyse',
|
||||
component: './vmcore/analyse',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
|
|
|
@ -67,7 +67,11 @@
|
|||
"react-dom": "^17.0.0",
|
||||
"react-helmet-async": "^1.0.4",
|
||||
"umi": "^3.5.0",
|
||||
"umi-serve": "^1.9.10"
|
||||
"umi-serve": "^1.9.10",
|
||||
"xterm": "^4.16.0",
|
||||
"xterm-addon-attach": "^0.6.0",
|
||||
"xterm-addon-fit": "^0.5.0",
|
||||
"xterm-addon-web-links": "^0.5.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@ant-design/pro-cli": "^2.0.2",
|
||||
|
|
|
@ -63,4 +63,5 @@ export default {
|
|||
'menu.diagnose': '诊断中心',
|
||||
'menu.diagnose.io': 'IO延时诊断',
|
||||
'menu.diagnose.net': '网络诊断',
|
||||
'menu.vmcore.analyse': '在线分析',
|
||||
};
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
import React, { useEffect, useRef } from 'react';
|
||||
import 'xterm/css/xterm.css';
|
||||
import { message } from 'antd';
|
||||
import { PageContainer } from '@ant-design/pro-layout';
|
||||
import { Terminal } from 'xterm';
|
||||
import { WebLinksAddon } from 'xterm-addon-web-links';
|
||||
import { FitAddon } from 'xterm-addon-fit';
|
||||
import { AttachAddon } from 'xterm-addon-attach';
|
||||
|
||||
const WebConsole = (props) => {
|
||||
const divRef = useRef(null);
|
||||
let socket = null;
|
||||
|
||||
const initTerminal = () => {
|
||||
const terminal = new Terminal({
|
||||
cursorBlink: true,
|
||||
});
|
||||
socket = new WebSocket(`ws://127.0.0.1:8001/ws/ssh/2/?user_id=1`);
|
||||
socket.onopen = () => {
|
||||
terminal.focus();
|
||||
};
|
||||
socket.onerror = () => {
|
||||
message.error('连接出错')
|
||||
};
|
||||
const webLinksAddon = new WebLinksAddon();
|
||||
const fitAddon = new FitAddon();
|
||||
const attachAddon = new AttachAddon(socket);
|
||||
terminal.loadAddon(webLinksAddon);
|
||||
terminal.loadAddon(fitAddon);
|
||||
terminal.loadAddon(attachAddon);
|
||||
terminal.open(divRef.current);
|
||||
fitAddon.fit();
|
||||
terminal.prompt = () => {
|
||||
terminal.write('\r\n ');
|
||||
};
|
||||
terminal.prompt();
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (socket) {
|
||||
socket.close();
|
||||
}
|
||||
initTerminal();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<PageContainer>
|
||||
<div style={{ marginTop: 10, width: 760, height: 500 }} ref={divRef} />;
|
||||
</PageContainer>
|
||||
)
|
||||
};
|
||||
|
||||
export default WebConsole
|
|
@ -17546,6 +17546,26 @@ xtend@^4.0.0:
|
|||
resolved "https://registry.npm.taobao.org/xtend/download/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
|
||||
integrity sha1-u3J3n1+kZRhrH0OPZ0+jR/2121Q=
|
||||
|
||||
xterm-addon-attach@^0.6.0:
|
||||
version "0.6.0"
|
||||
resolved "https://registry.npmmirror.com/xterm-addon-attach/download/xterm-addon-attach-0.6.0.tgz#220c23addd62ab88c9914e2d4c06f7407e44680e"
|
||||
integrity sha1-Igwjrd1iq4jJkU4tTAb3QH5EaA4=
|
||||
|
||||
xterm-addon-fit@^0.5.0:
|
||||
version "0.5.0"
|
||||
resolved "https://registry.npmmirror.com/xterm-addon-fit/download/xterm-addon-fit-0.5.0.tgz#2d51b983b786a97dcd6cde805e700c7f913bc596"
|
||||
integrity sha1-LVG5g7eGqX3NbN6AXnAMf5E7xZY=
|
||||
|
||||
xterm-addon-web-links@^0.5.0:
|
||||
version "0.5.0"
|
||||
resolved "https://registry.npmmirror.com/xterm-addon-web-links/download/xterm-addon-web-links-0.5.0.tgz#c6869c0032e6709e2437315199d794a3b94a183e"
|
||||
integrity sha512-egDNFDvuArQ0QKE/ZdP1HMo70Lm8nSOjuIJY0kYjqCCE6yntjyuGzjeoYD+CIQ12gJ6B6thVh8nTApi27qYiag==
|
||||
|
||||
xterm@^4.16.0:
|
||||
version "4.16.0"
|
||||
resolved "https://registry.npmmirror.com/xterm/download/xterm-4.16.0.tgz#af25223c72917438842121e1bcd1b60ffd7e8476"
|
||||
integrity sha512-nAbuigL9CYkI075mdfqpnB8cHZNKxENCj1CQ9Tm5gSvWkMtkanmRN2mkHGjSaET1/3+X9BqISFFo7Pd2mXVjiQ==
|
||||
|
||||
y18n@^4.0.0:
|
||||
version "4.0.3"
|
||||
resolved "https://registry.npm.taobao.org/y18n/download/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf"
|
||||
|
|
Loading…
Reference in New Issue