From 8ed2e800f68f05718930890ab8481af821420a28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=89=91=E5=AD=90=E4=BB=99=E6=9C=BA?= Date: Fri, 14 Jan 2022 03:39:38 +0000 Subject: [PATCH] =?UTF-8?q?!17=20webconsole=E7=BB=88=E7=AB=AF=E5=9F=BA?= =?UTF-8?q?=E6=9C=AC=E5=8A=9F=E8=83=BD=E8=B0=83=E9=80=9A=20*=20webconsole?= =?UTF-8?q?=E7=BB=88=E7=AB=AF=E5=9F=BA=E6=9C=AC=E5=8A=9F=E8=83=BD=E8=B0=83?= =?UTF-8?q?=E9=80=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sysom_api/apps/host/models.py | 4 +- sysom_api/conf/__init__.py | 1 - sysom_api/consumer/consumers.py | 10 +--- sysom_api/consumer/executors.py | 3 +- sysom_api/consumer/middleware.py | 7 ++- sysom_api/consumer/routing.py | 1 - sysom_api/sysom/asgi.py | 14 +++++- sysom_api/sysom/settings.py | 21 -------- sysom_web/config/routes.js | 5 ++ sysom_web/package.json | 6 ++- sysom_web/src/locales/zh-CN/menu.js | 1 + sysom_web/src/pages/vmcore/analyse/index.jsx | 53 ++++++++++++++++++++ sysom_web/yarn.lock | 20 ++++++++ 13 files changed, 104 insertions(+), 42 deletions(-) create mode 100644 sysom_web/src/pages/vmcore/analyse/index.jsx diff --git a/sysom_api/apps/host/models.py b/sysom_api/apps/host/models.py index 397d766..074095f 100644 --- a/sysom_api/apps/host/models.py +++ b/sysom_api/apps/host/models.py @@ -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): diff --git a/sysom_api/conf/__init__.py b/sysom_api/conf/__init__.py index c9e99e0..fc6d05c 100644 --- a/sysom_api/conf/__init__.py +++ b/sysom_api/conf/__init__.py @@ -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'. diff --git a/sysom_api/consumer/consumers.py b/sysom_api/consumer/consumers.py index 791a046..e7e043f 100644 --- a/sysom_api/consumer/consumers.py +++ b/sysom_api/consumer/consumers.py @@ -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() \ No newline at end of file diff --git a/sysom_api/consumer/executors.py b/sysom_api/consumer/executors.py index ef6d82d..079ba32 100644 --- a/sysom_api/consumer/executors.py +++ b/sysom_api/consumer/executors.py @@ -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) diff --git a/sysom_api/consumer/middleware.py b/sysom_api/consumer/middleware.py index fc4d65c..b5696c7 100644 --- a/sysom_api/consumer/middleware.py +++ b/sysom_api/consumer/middleware.py @@ -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) diff --git a/sysom_api/consumer/routing.py b/sysom_api/consumer/routing.py index 1938750..a1e1507 100644 --- a/sysom_api/consumer/routing.py +++ b/sysom_api/consumer/routing.py @@ -5,7 +5,6 @@ from .middleware import AuthMiddleware ws_router = AuthMiddleware( URLRouter([ - path('ws/exec//', ExecConsumer.as_asgi()), path('ws/ssh//', SshConsumer.as_asgi()), ]) ) diff --git a/sysom_api/sysom/asgi.py b/sysom_api/sysom/asgi.py index 7c029dd..76fd715 100644 --- a/sysom_api/sysom/asgi.py +++ b/sysom_api/sysom/asgi.py @@ -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//', SshConsumer.as_asgi()), + ]) + ) +}) diff --git a/sysom_api/sysom/settings.py b/sysom_api/sysom/settings.py index 5c8b5f4..f46326c 100644 --- a/sysom_api/sysom/settings.py +++ b/sysom_api/sysom/settings.py @@ -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 diff --git a/sysom_web/config/routes.js b/sysom_web/config/routes.js index 33caeb5..d4348e0 100644 --- a/sysom_web/config/routes.js +++ b/sysom_web/config/routes.js @@ -74,6 +74,11 @@ export default [ name: 'match', component: './vmcore/match', }, + { + path: '/vmcore/analyse', + name: 'analyse', + component: './vmcore/analyse', + }, ], }, { diff --git a/sysom_web/package.json b/sysom_web/package.json index 11bc3e9..2d90a4e 100644 --- a/sysom_web/package.json +++ b/sysom_web/package.json @@ -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", diff --git a/sysom_web/src/locales/zh-CN/menu.js b/sysom_web/src/locales/zh-CN/menu.js index 8bd130f..542c689 100644 --- a/sysom_web/src/locales/zh-CN/menu.js +++ b/sysom_web/src/locales/zh-CN/menu.js @@ -63,4 +63,5 @@ export default { 'menu.diagnose': '诊断中心', 'menu.diagnose.io': 'IO延时诊断', 'menu.diagnose.net': '网络诊断', + 'menu.vmcore.analyse': '在线分析', }; diff --git a/sysom_web/src/pages/vmcore/analyse/index.jsx b/sysom_web/src/pages/vmcore/analyse/index.jsx new file mode 100644 index 0000000..5939a94 --- /dev/null +++ b/sysom_web/src/pages/vmcore/analyse/index.jsx @@ -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 ( + +
; + + ) +}; + +export default WebConsole \ No newline at end of file diff --git a/sysom_web/yarn.lock b/sysom_web/yarn.lock index 0980883..e830f18 100644 --- a/sysom_web/yarn.lock +++ b/sysom_web/yarn.lock @@ -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"