256 lines
		
	
	
		
			8.6 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			256 lines
		
	
	
		
			8.6 KiB
		
	
	
	
		
			Python
		
	
	
	
 | 
						||
from django.shortcuts import render
 | 
						||
from rest_framework.response import Response
 | 
						||
from rest_framework.views import APIView
 | 
						||
from rest_framework.permissions import IsAuthenticated
 | 
						||
from django.conf import settings
 | 
						||
import os
 | 
						||
from apps.ops.serializers import DbbackupDeleteSerializer, MemDiskSerializer, CpuSerializer, DrfRequestLogSerializer, TlogSerializer, TextListSerializer
 | 
						||
from rest_framework.exceptions import NotFound
 | 
						||
from rest_framework.mixins import ListModelMixin
 | 
						||
from apps.ops.filters import DrfLogFilterSet, TlogFilterSet
 | 
						||
from apps.ops.models import DrfRequestLog, Tlog
 | 
						||
 | 
						||
from apps.ops.errors import LOG_NOT_FONED
 | 
						||
from apps.utils.viewsets import CustomGenericViewSet
 | 
						||
from rest_framework.exceptions import APIException
 | 
						||
from apps.ops.tasks import reload_server_git, reload_server_only, reload_web_git, backup_database, backup_media
 | 
						||
from rest_framework.permissions import IsAdminUser
 | 
						||
from drf_yasg.utils import swagger_auto_schema
 | 
						||
from apps.ops.service import ServerService
 | 
						||
from server.settings import BACKUP_PATH
 | 
						||
# Create your views here.
 | 
						||
 | 
						||
 | 
						||
def index(request):
 | 
						||
    return render(request, 'ops/index.html')
 | 
						||
 | 
						||
 | 
						||
def room(request, room_name):
 | 
						||
    return render(request, 'ops/room.html', {
 | 
						||
        'room_name': room_name
 | 
						||
    })
 | 
						||
 | 
						||
 | 
						||
class ReloadServerGit(APIView):
 | 
						||
    permission_classes = [IsAdminUser]
 | 
						||
 | 
						||
    @swagger_auto_schema(operation_summary="拉取后端代码并重启服务", responses=None, request_body=None)
 | 
						||
    def post(self, request):
 | 
						||
        reload_server_git.delay()
 | 
						||
        return Response()
 | 
						||
        # if completed.returncode == 0:
 | 
						||
        #     return Response()
 | 
						||
        # else:
 | 
						||
        #     from server.settings import myLogger
 | 
						||
        #     myLogger.error(completed)
 | 
						||
        #     raise ParseError(completed.stderr)
 | 
						||
 | 
						||
 | 
						||
class ReloadClientGit(APIView):
 | 
						||
    permission_classes = [IsAdminUser]
 | 
						||
 | 
						||
    @swagger_auto_schema(operation_summary="拉取前端代码并打包", responses=None, request_body=None)
 | 
						||
    def post(self, request):
 | 
						||
        reload_web_git.delay()
 | 
						||
        return Response()
 | 
						||
        # completed = reload_web_git()
 | 
						||
        # if completed.returncode == 0:
 | 
						||
        #     return Response()
 | 
						||
        # else:
 | 
						||
        #     raise APIException(completed.stdout)
 | 
						||
 | 
						||
 | 
						||
class ReloadServerOnly(APIView):
 | 
						||
    permission_classes = [IsAdminUser]
 | 
						||
 | 
						||
    @swagger_auto_schema(operation_summary="仅重启服务", responses=None, request_body=None)
 | 
						||
    def post(self, request):
 | 
						||
        completed = reload_server_only()
 | 
						||
        if completed.returncode == 0:
 | 
						||
            return Response()
 | 
						||
        else:
 | 
						||
            raise APIException(completed.stdout)
 | 
						||
 | 
						||
 | 
						||
class BackupDatabase(APIView):
 | 
						||
    permission_classes = [IsAdminUser]
 | 
						||
 | 
						||
    @swagger_auto_schema(operation_summary="备份数据库到指定位置", responses=None, request_body=None)
 | 
						||
    def post(self, request):
 | 
						||
        err_str = backup_database()
 | 
						||
        if err_str:
 | 
						||
            raise APIException(err_str)
 | 
						||
        return Response()
 | 
						||
 | 
						||
 | 
						||
class BackupMedia(APIView):
 | 
						||
    permission_classes = [IsAdminUser]
 | 
						||
 | 
						||
    @swagger_auto_schema(operation_summary="备份资源到指定位置", responses=None, request_body=None)
 | 
						||
    def post(self, request):
 | 
						||
        err_str = backup_media()
 | 
						||
        if err_str:
 | 
						||
            raise APIException(err_str)
 | 
						||
        return Response()
 | 
						||
 | 
						||
 | 
						||
class CpuView(APIView):
 | 
						||
    permission_classes = [IsAuthenticated]
 | 
						||
 | 
						||
    @swagger_auto_schema(operation_summary="获取服务器cpu当前状态", responses={200: CpuSerializer}, request_body=None)
 | 
						||
    def get(self, request, *args, **kwargs):
 | 
						||
        return Response(ServerService.get_cpu_dict())
 | 
						||
 | 
						||
 | 
						||
class MemoryView(APIView):
 | 
						||
    permission_classes = [IsAuthenticated]
 | 
						||
 | 
						||
    @swagger_auto_schema(operation_summary="获取服务器内存当前状态", responses={200: MemDiskSerializer}, request_body=None)
 | 
						||
    def get(self, request, *args, **kwargs):
 | 
						||
        return Response(ServerService.get_memory_dict())
 | 
						||
 | 
						||
 | 
						||
class DiskView(APIView):
 | 
						||
    permission_classes = [IsAuthenticated]
 | 
						||
 | 
						||
    @swagger_auto_schema(operation_summary="获取服务器硬盘当前状态", responses={200: MemDiskSerializer}, request_body=None)
 | 
						||
    def get(self, request, *args, **kwargs):
 | 
						||
        return Response(ServerService.get_disk_dict())
 | 
						||
 | 
						||
 | 
						||
def get_file_list(file_path):
 | 
						||
    dir_list = os.listdir(file_path)
 | 
						||
    if not dir_list:
 | 
						||
        return
 | 
						||
    else:
 | 
						||
        # 注意,这里使用lambda表达式,将文件按照最后修改时间顺序升序排列
 | 
						||
        # os.path.getmtime() 函数是获取文件最后修改时间
 | 
						||
        # os.path.getctime() 函数是获取文件最后创建时间
 | 
						||
        dir_list = sorted(dir_list, key=lambda x: os.path.getmtime(
 | 
						||
            os.path.join(file_path, x)), reverse=True)
 | 
						||
        # print(dir_list)
 | 
						||
        return dir_list
 | 
						||
 | 
						||
 | 
						||
class LogView(APIView):
 | 
						||
    permission_classes = [IsAuthenticated]
 | 
						||
 | 
						||
    @swagger_auto_schema(operation_summary="查看最近的日志列表", responses={200: TextListSerializer(many=True)}, request_body=None)
 | 
						||
    def get(self, request, *args, **kwargs):
 | 
						||
        logs = []
 | 
						||
        name = request.GET.get('name', None)
 | 
						||
        # for root, dirs, files in os.walk(settings.LOG_PATH):
 | 
						||
        #     files.reverse()
 | 
						||
        for file in get_file_list(settings.LOG_PATH):
 | 
						||
            if len(logs) > 50:
 | 
						||
                break
 | 
						||
            filepath = os.path.join(settings.LOG_PATH, file)
 | 
						||
            if name:
 | 
						||
                if name in filepath:
 | 
						||
                    fsize = os.path.getsize(filepath)
 | 
						||
                    if fsize:
 | 
						||
                        logs.append({
 | 
						||
                            "name": file,
 | 
						||
                            "filepath": filepath,
 | 
						||
                            "size": round(fsize/1024, 1)
 | 
						||
                        })
 | 
						||
            else:
 | 
						||
                fsize = os.path.getsize(filepath)
 | 
						||
                if fsize:
 | 
						||
                    logs.append({
 | 
						||
                        "name": file,
 | 
						||
                        "filepath": filepath,
 | 
						||
                        "size": round(fsize/1024, 1)
 | 
						||
                    })
 | 
						||
        return Response(logs)
 | 
						||
 | 
						||
 | 
						||
class LogDetailView(APIView):
 | 
						||
    permission_classes = [IsAuthenticated]
 | 
						||
 | 
						||
    @swagger_auto_schema(operation_summary="查看日志详情", responses=None)
 | 
						||
    def get(self, request, name):
 | 
						||
        try:
 | 
						||
            with open(os.path.join(settings.LOG_PATH, name)) as f:
 | 
						||
                data = f.read()
 | 
						||
            return Response(data)
 | 
						||
        except Exception:
 | 
						||
            raise NotFound(**LOG_NOT_FONED)
 | 
						||
 | 
						||
 | 
						||
class DbBackupDeleteView(APIView):
 | 
						||
    perms_map = {'delete': 'dbback.delete'}
 | 
						||
 | 
						||
    @swagger_auto_schema(operation_summary="删除备份", responses={204: None})
 | 
						||
    def delete(self, request, filepath):
 | 
						||
        if BACKUP_PATH in filepath:
 | 
						||
            os.remove(filepath)
 | 
						||
        return Response()
 | 
						||
 | 
						||
 | 
						||
class DbBackupView(APIView):
 | 
						||
    perms_map = {'get': '*', 'post': 'dbback.delete'}
 | 
						||
 | 
						||
    @swagger_auto_schema(operation_summary="批量删除备份", responses={204: None}, request_body=DbbackupDeleteSerializer)
 | 
						||
    def post(self, request):
 | 
						||
        filepaths = request.data.get('filepaths', [])
 | 
						||
        for i in filepaths:
 | 
						||
            if BACKUP_PATH in i:
 | 
						||
                os.remove(i)
 | 
						||
        return Response()
 | 
						||
 | 
						||
    @swagger_auto_schema(operation_summary="查看最近的备份列表", responses={200: TextListSerializer(many=True)}, request_body=None)
 | 
						||
    def get(self, request, *args, **kwargs):
 | 
						||
        items = []
 | 
						||
        name = request.GET.get('name', None)
 | 
						||
        backpath = settings.BACKUP_PATH + '/database'
 | 
						||
        for file in get_file_list(backpath):
 | 
						||
            if len(items) > 50:
 | 
						||
                break
 | 
						||
            filepath = os.path.join(backpath, file)
 | 
						||
            if name:
 | 
						||
                if name in filepath:
 | 
						||
                    fsize = os.path.getsize(filepath)
 | 
						||
                    if fsize:
 | 
						||
                        items.append({
 | 
						||
                            "name": file,
 | 
						||
                            "filepath": filepath,
 | 
						||
                            "size": round(fsize/1024/1024, 1)
 | 
						||
                        })
 | 
						||
            else:
 | 
						||
                fsize = os.path.getsize(filepath)
 | 
						||
                if fsize:
 | 
						||
                    items.append({
 | 
						||
                        "name": file,
 | 
						||
                        "filepath": filepath,
 | 
						||
                        "size": round(fsize/1024/1024, 1)
 | 
						||
                    })
 | 
						||
        return Response(items)
 | 
						||
 | 
						||
 | 
						||
class DrfRequestLogViewSet(ListModelMixin, CustomGenericViewSet):
 | 
						||
    """list:请求日志
 | 
						||
 | 
						||
    请求日志
 | 
						||
    """
 | 
						||
    perms_map = {'get': '*'}
 | 
						||
    queryset = DrfRequestLog.objects.all()
 | 
						||
    list_serializer_class = DrfRequestLogSerializer
 | 
						||
    ordering = ['-requested_at']
 | 
						||
    filterset_class = DrfLogFilterSet
 | 
						||
    search_fields = ['path', 'view']
 | 
						||
 | 
						||
 | 
						||
class TlogViewSet(ListModelMixin, CustomGenericViewSet):
 | 
						||
    """list:三方日志查看
 | 
						||
 | 
						||
    三方日志查看
 | 
						||
    """
 | 
						||
    perms_map = {'get': '*'}
 | 
						||
    queryset = Tlog.objects.all()
 | 
						||
    list_serializer_class = TlogSerializer
 | 
						||
    ordering = ['-requested_at']
 | 
						||
    filterset_class = TlogFilterSet
 | 
						||
    search_fields = ['path']
 |