From 9d8c74e76814e198e075b879756dfc9338e13b48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E5=BC=BA?= <1206709430@qq.com> Date: Sun, 11 Apr 2021 01:28:06 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=8A=9F=E8=83=BD(=E6=9C=8D=E5=8A=A1?= =?UTF-8?q?=E5=99=A8=E7=9B=91=E6=8E=A7):=20=E6=96=B0=E5=A2=9E=E6=9C=8D?= =?UTF-8?q?=E5=8A=A1=E5=99=A8=E7=9B=91=E6=8E=A7=E5=8A=9F=E8=83=BDAPI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dvadmin-backend/application/settings.py | 1 + dvadmin-backend/application/urls.py | 2 +- .../apps/vadmin/monitor/models/monitor.py | 4 +- .../apps/vadmin/monitor/models/server.py | 7 +- .../apps/vadmin/monitor/models/sys_files.py | 4 +- dvadmin-backend/apps/vadmin/monitor/tasks.py | 89 ++++++++++++++++++ dvadmin-backend/apps/vadmin/monitor/urls.py | 5 +- dvadmin-backend/apps/vadmin/monitor/views.py | 93 +++++++++++++++++++ dvadmin-backend/requirements.txt | 1 + 9 files changed, 197 insertions(+), 9 deletions(-) diff --git a/dvadmin-backend/application/settings.py b/dvadmin-backend/application/settings.py index 7132864..0e9601d 100644 --- a/dvadmin-backend/application/settings.py +++ b/dvadmin-backend/application/settings.py @@ -329,3 +329,4 @@ CELERYBEAT_SCHEDULER = 'django_celery_beat.schedulers.DatabaseScheduler' # Back # ================================================= # # 接口权限 INTERFACE_PERMISSION = {locals().get("INTERFACE_PERMISSION", False)} +DJANGO_CELERY_BEAT_TZ_AWARE = False diff --git a/dvadmin-backend/application/urls.py b/dvadmin-backend/application/urls.py index 1bd1ed6..2a3a0ae 100644 --- a/dvadmin-backend/application/urls.py +++ b/dvadmin-backend/application/urls.py @@ -22,7 +22,7 @@ from django.urls import re_path, include from django.views.static import serve from rest_framework.views import APIView -from vadmin.utils.response import SuccessResponse +from apps.vadmin.utils.response import SuccessResponse class CaptchaRefresh(APIView): diff --git a/dvadmin-backend/apps/vadmin/monitor/models/monitor.py b/dvadmin-backend/apps/vadmin/monitor/models/monitor.py index 5a883d6..121ec8c 100644 --- a/dvadmin-backend/apps/vadmin/monitor/models/monitor.py +++ b/dvadmin-backend/apps/vadmin/monitor/models/monitor.py @@ -5,12 +5,10 @@ from ...op_drf.models import CoreModel class Monitor(CoreModel): cpu_num = CharField(max_length=8, verbose_name='CPU核数') - cpu_free = CharField(max_length=8, verbose_name='CPU当前空闲率') cpu_sys = CharField(max_length=8, verbose_name='CPU已使用率') mem_num = CharField(max_length=32, verbose_name='内存总数(KB)') - mem_free = CharField(max_length=32, verbose_name='内存剩余大小(KB)') mem_sys = CharField(max_length=32, verbose_name='内存已使用大小(KB)') - seconds = CharField(max_length=32, verbose_name='运行已时间(秒)') + seconds = CharField(max_length=32, verbose_name='系统已运行时间') server = ForeignKey(to='Server', on_delete=CASCADE, verbose_name="关联服务器信息", db_constraint=False) class Meta: diff --git a/dvadmin-backend/apps/vadmin/monitor/models/server.py b/dvadmin-backend/apps/vadmin/monitor/models/server.py index aebc802..d05140f 100644 --- a/dvadmin-backend/apps/vadmin/monitor/models/server.py +++ b/dvadmin-backend/apps/vadmin/monitor/models/server.py @@ -1,13 +1,16 @@ +from django.db import models from django.db.models import CharField -from ...op_drf.models import CoreModel +from apps.vadmin.op_drf.fields import UpdateDateTimeField, CreateDateTimeField -class Server(CoreModel): +class Server(models.Model): name = CharField(max_length=256, verbose_name='服务器名称', null=True, blank=True) ip = CharField(max_length=32, verbose_name="ip地址") os = CharField(max_length=32, verbose_name="操作系统") remark = CharField(max_length=256, verbose_name="备注", null=True, blank=True) + update_datetime = UpdateDateTimeField() # 修改时间 + create_datetime = CreateDateTimeField() # 创建时间 class Meta: verbose_name = '服务器信息' diff --git a/dvadmin-backend/apps/vadmin/monitor/models/sys_files.py b/dvadmin-backend/apps/vadmin/monitor/models/sys_files.py index 6a11ed1..a7ce4e1 100644 --- a/dvadmin-backend/apps/vadmin/monitor/models/sys_files.py +++ b/dvadmin-backend/apps/vadmin/monitor/models/sys_files.py @@ -5,10 +5,10 @@ from ...op_drf.models import CoreModel class SysFiles(CoreModel): dir_name = CharField(max_length=32, verbose_name='磁盘路径') - sys_type_name = CharField(max_length=32, verbose_name='系统文件类型') + sys_type_name = CharField(max_length=400, verbose_name='系统文件类型') type_name = CharField(max_length=32, verbose_name='盘符类型') total = CharField(max_length=32, verbose_name='磁盘总大小(KB)') - mem_free = CharField(max_length=32, verbose_name='已使用大小(KB)') + disk_sys = CharField(max_length=32, verbose_name='已使用大小(KB)') monitor = ForeignKey(to='Monitor', on_delete=CASCADE, verbose_name="关联服务器监控信息", db_constraint=False) class Meta: diff --git a/dvadmin-backend/apps/vadmin/monitor/tasks.py b/dvadmin-backend/apps/vadmin/monitor/tasks.py index e69de29..ba734f7 100644 --- a/dvadmin-backend/apps/vadmin/monitor/tasks.py +++ b/dvadmin-backend/apps/vadmin/monitor/tasks.py @@ -0,0 +1,89 @@ +import datetime +import logging +import sys +import time + +import psutil + +from ..monitor.models import Server, Monitor, SysFiles +from ..op_drf.response import SuccessResponse +from ..system.models import ConfigSettings +from ..utils.decorators import BaseCeleryApp + +logger = logging.getLogger(__name__) +from platform import platform + + +def getIP(): + """获取ipv4地址""" + dic = psutil.net_if_addrs() + ipv4_list = [] + for adapter in dic: + snicList = dic[adapter] + for snic in snicList: + if snic.family.name == 'AF_INET': + ipv4 = snic.address + if ipv4 != '127.0.0.1': + ipv4_list.append(ipv4) + if len(ipv4_list) >= 1: + return ipv4_list[0] + else: + return None + + +@BaseCeleryApp(name='apps.vadmin.monitor.tasks.get_monitor_info') +def get_monitor_info(): + """ + 定时获取系统监控信息 + :return: + """ + # 获取服务器 + ip = getIP() + if not ip: + logger.error("无法获取到IP") + return + server_obj, create = Server.objects.get_or_create(ip=ip) + if create: + server_obj.name = ip + terse = ('terse' in sys.argv or '--terse' in sys.argv) + aliased = (not 'nonaliased' in sys.argv and not '--nonaliased' in sys.argv) + server_obj.os = platform(aliased, terse) + server_obj.save() + + # 获取CPU和内存信息 + mem = psutil.virtual_memory() + monitor_obj = Monitor() + monitor_obj.cpu_num = psutil.cpu_count() + monitor_obj.cpu_sys = float(psutil.cpu_percent(0.1)) + monitor_obj.mem_num = int(mem.total / 1024) + monitor_obj.mem_sys = int(mem.used / 1024) + monitor_obj.seconds = time.strftime("%d天 %H 小时 %M 分 %S 秒", time.gmtime(int(time.time()) - int(psutil.boot_time()))) + monitor_obj.server = server_obj + monitor_obj.save() + + # 保存磁盘信息 + for ele in psutil.disk_partitions(): + disk = psutil.disk_usage('/') + + sys_files_obj = SysFiles() + sys_files_obj.dir_name = ele.mountpoint + sys_files_obj.sys_type_name = ele.opts + sys_files_obj.type_name = ele.fstype + sys_files_obj.total = disk.total + sys_files_obj.disk_sys = disk.used + sys_files_obj.monitor = monitor_obj + sys_files_obj.save() + + return SuccessResponse(msg="") + + +@BaseCeleryApp(name='apps.vadmin.monitor.tasks.clean_surplus_monitor_info') +def clean_surplus_monitor_info(): + """ + 定时清理多余 系统监控信息 + :return: + """ + config_settings_obj = ConfigSettings.objects.filter(configKey='sys.monitor.info.save_days').first() + Monitor.objects.filter( + update_datetime__lt=datetime.timedelta(days=int(config_settings_obj.configValue or 30))).delete() + logger.info(f"成功清空{config_settings_obj.configValue}天前数据") diff --git a/dvadmin-backend/apps/vadmin/monitor/urls.py b/dvadmin-backend/apps/vadmin/monitor/urls.py index b1c0b78..c5ef2fa 100644 --- a/dvadmin-backend/apps/vadmin/monitor/urls.py +++ b/dvadmin-backend/apps/vadmin/monitor/urls.py @@ -1,3 +1,4 @@ +from django.urls import re_path from rest_framework.routers import DefaultRouter from .views import ServerModelViewSet, MonitorModelViewSet @@ -7,6 +8,8 @@ router.register(r'server', ServerModelViewSet) router.register(r'monitor', MonitorModelViewSet) urlpatterns = [ - + re_path('monitor/info/', MonitorModelViewSet.as_view({'get': 'get_monitor_info'})), + re_path('monitor/enabled/', MonitorModelViewSet.as_view({'get': 'enabled_monitor_info'})), + re_path('monitor/clean/', MonitorModelViewSet.as_view({'get': 'clean_all'})), ] urlpatterns += router.urls diff --git a/dvadmin-backend/apps/vadmin/monitor/views.py b/dvadmin-backend/apps/vadmin/monitor/views.py index e4cec1c..9325852 100644 --- a/dvadmin-backend/apps/vadmin/monitor/views.py +++ b/dvadmin-backend/apps/vadmin/monitor/views.py @@ -1,8 +1,13 @@ +from django_celery_beat.models import PeriodicTask, IntervalSchedule, CrontabSchedule +from rest_framework.request import Request + from .filters import ServerFilter, MonitorFilter from .models import Server, Monitor from .serializers import ServerSerializer, MonitorSerializer +from ..op_drf.response import SuccessResponse from ..op_drf.viewsets import CustomModelViewSet from ..permission.permissions import CommonPermission +from ..system.models import ConfigSettings class ServerModelViewSet(CustomModelViewSet): @@ -18,6 +23,7 @@ class ServerModelViewSet(CustomModelViewSet): create_extra_permission_classes = (CommonPermission,) ordering = '-create_datetime' # 默认排序 + class MonitorModelViewSet(CustomModelViewSet): """ 服务器监控信息 模型的CRUD视图 @@ -30,3 +36,90 @@ class MonitorModelViewSet(CustomModelViewSet): destroy_extra_permission_classes = (CommonPermission,) create_extra_permission_classes = (CommonPermission,) ordering = '-create_datetime' # 默认排序 + + def get_monitor_info(self, request: Request, *args, **kwargs): + # 定时获取系统监控信息 + periodictask_obj = PeriodicTask.objects.filter(task='apps.vadmin.monitor.tasks.get_monitor_info').first() + if not periodictask_obj: + intervalschedule_obj, _ = IntervalSchedule.objects.get_or_create(every=5, period="seconds") + periodictask_obj = PeriodicTask() + periodictask_obj.task = "apps.vadmin.monitor.tasks.get_monitor_info" + periodictask_obj.name = "定时获取系统监控信息" + periodictask_obj.interval = intervalschedule_obj + periodictask_obj.enabled = False + periodictask_obj.save() + + # 定时清理多余 系统监控信息 + clean_task_obj = PeriodicTask.objects.filter( + task='apps.vadmin.monitor.tasks.clean_surplus_monitor_info').first() + if not clean_task_obj: + crontab_obj, _ = CrontabSchedule.objects.get_or_create(day_of_month="*", day_of_week="*", hour="1", + minute="0", month_of_year="*") + clean_task_obj = PeriodicTask() + clean_task_obj.task = "apps.vadmin.monitor.tasks.clean_surplus_monitor_info" + clean_task_obj.name = "定时清理多余-系统监控信息" + clean_task_obj.crontab = crontab_obj + clean_task_obj.enabled = True + clean_task_obj.save() + # 配置添加 + config_obj = ConfigSettings.objects.filter(configKey='sys.monitor.info.save_days').first() + if not config_obj: + config_obj = ConfigSettings() + config_obj.configKey = "sys.monitor.info.save_days" + config_obj.configName = "定时清理多余系统监控信息" + config_obj.configValue = "30" + config_obj.configType = "Y" + config_obj.status = "1" + config_obj.remark = "定时清理多余-系统监控信息,默认30天" + config_obj.save() + + # 获取保留天数 + return SuccessResponse(data={ + "enabled": periodictask_obj.enabled, + "interval": periodictask_obj.interval.every, + "save_days": config_obj.configValue if config_obj else "30", + }) + + def enabled_monitor_info(self, request: Request, *args, **kwargs): + enabled = request.query_params.get('enabled', None) + save_days = request.query_params.get('save_days', None) + interval = request.query_params.get('interval', None) + + periodictask_obj = PeriodicTask.objects.filter(task='apps.vadmin.monitor.tasks.get_monitor_info').first() + if enabled: + # 更新监控状态 + periodictask_obj.enabled = True if enabled == "1" else False + periodictask_obj.save() + + # 更新 定时清理多余 系统监控信息 状态 + clean_task_obj = PeriodicTask.objects.filter( + task='apps.vadmin.monitor.tasks.clean_surplus_monitor_info').first() + clean_task_obj.enabled = True if enabled == "1" else False + clean_task_obj.save() + # 更新保留天数 + config_obj = ConfigSettings.objects.filter(configKey='sys.monitor.info.save_days').first() + print(33, save_days) + print(22, config_obj) + if save_days and config_obj: + config_obj.configValue = save_days + config_obj.save() + # 更新监控获取频率 + if interval: + periodictask_obj.interval.every = interval + periodictask_obj.interval.save() + return SuccessResponse(data={ + "enabled": periodictask_obj.enabled, + "interval": periodictask_obj.interval.every, + "save_days": config_obj.configValue if config_obj else "30", + }) + + def clean_all(self, request: Request, *args, **kwargs): + """ + 清空监控信息 + :param request: + :param args: + :param kwargs: + :return: + """ + self.get_queryset().delete() + return SuccessResponse(msg="清空成功") diff --git a/dvadmin-backend/requirements.txt b/dvadmin-backend/requirements.txt index 5e06ebc..2ea4f69 100644 --- a/dvadmin-backend/requirements.txt +++ b/dvadmin-backend/requirements.txt @@ -26,3 +26,4 @@ xlrd==2.0.1 coreapi==2.3.3 user-agents==2.2.0 eventlet==0.30.2 +psutil==5.8.0