zoukankan      html  css  js  c++  java
  • 【实例:利用Django管理后台管理IP地址】(五)编写views函数检测每个ip地址占用情况

    定制相关数据的展示之后,还需要实现一些功能便于告知用户当前IP地址实际占用情况

    需求包括:

    1、多线程并发执行对每个IP地址的操作

    2、规则:(表字段包括:ip地址、ip使用状态、使用人ID、使用人用户名、备注信息、非法使用天数、无法连接天数)

    ①若当前IP属于空闲,实际情况:ping通 —> 表示被非法使用,则非法使用天数+1;ping不通 —> 正常情况,因为不被使用,非法使用天数=0,表示已经恢复正常状态

    ②若当前IP属于使用中,实际情况:ping不通 —> 表示已经不被使用,无法连接天数+1;ping通 —> 正常情况,因为正在使用,无法连接天数=0,表示已经恢复正常状态

    ③若当前IP属于空闲,若无法连接天数>0,则执行无法连接天数=0,因为无法连接属于正常状况,清除之前的遗留数据;

    ④若当前IP属于使用中,若非法使用天数>0,则执行非法使用天数=0,因为能连接属于正常状况,清除之前的遗留数据;

    所以这里的非法使用天数、无法连接天数都是讲究连续性的,偶尔一两天的不正常状态可能是断电断网/临时借用一两小时,如果连续7天或者20天告警说明是真的没有通知的情况下使用了或者IP已经不被使用了。

    views.py

    凡是被标注【#把print改成写入日志】的都是当前调试打印出来观察的,之后计划改成写入日志的

     1 from mysiteapp.models import ipaddr_info
     2 # Create your views here.
     3 import subprocess
     4 import threading
     5 
     6 
     7 # 检查IP是否被占用
     8 def get_ping_result(ip):
     9     cmd_str = "ping {0} -n 4 -w 600".format(ip)
    10     DETACHED_PROCESS = 0x00000008   # 不创建cmd窗口
    11     try:
    12         subprocess.run(cmd_str, creationflags=DETACHED_PROCESS, check=True)  # 仅用于windows系统
    13     except subprocess.CalledProcessError as err:
    14         print("ping不通"+ip)  #把print改成写入日志
    15         return 0
    16     else:
    17         print("ping通"+ip)  # 把print改成写入日志
    18         return 1
    19 
    20 #处理规则
    21 def ip_status_alarm(ip):
    22     x = get_ping_result(ip)
    23     try:
    24         ipobj = ipaddr_info.objects.get(ipaddr=ip)
    25     except ipaddr_info.DoesNotExist:
    26         print("Address does not exit!")
    27     else:
    28         if ipobj.ipstatus == 0:
    29             print("0,空闲", ip)  #把print改成写入日志
    30             if x == 1:
    31                 print("1,ping通", ip)  # 把print改成写入日志
    32                 # 取出connect_alarm_num告警数,+1,存回数据库
    33                 connect_alarm_num0 = ipobj.connect_alarm_num + 1
    34                 ipaddr_info.objects.filter(ipaddr=ip).update(connect_alarm_num=connect_alarm_num0)
    35             else:
    36                 print("1,ping不通", ip)  # 把print改成写入日志
    37                 ipaddr_info.objects.filter(ipaddr=ip).update(connect_alarm_num=0)
    38             if ipobj.disconnect_alarm_num > 0:
    39                 # 如果disconnect_alarm_num告警数>0,置为0
    40                 ipaddr_info.objects.filter(ipaddr=ip).update(disconnect_alarm_num=0)
    41         else:
    42             print("1,使用中", ip)#把print改成写入日志
    43             if x == 0:
    44                 print("1,ping不通", ip)  # 把print改成写入日志
    45                 #  取出disconnect_alarm_num告警数,+1
    46                 disconnect_alarm_num1 = ipobj.disconnect_alarm_num + 1
    47                 ipaddr_info.objects.filter(ipaddr=ip).update(disconnect_alarm_num=disconnect_alarm_num1)
    48             else:
    49                 print("1,ping通", ip)  # 把print改成写入日志
    50                 ipaddr_info.objects.filter(ipaddr=ip).update(disconnect_alarm_num=0)
    51             if ipobj.connect_alarm_num > 0:
    52                 # 如果connect_alarm_num告警数>0,置为0
    53                 ipaddr_info.objects.filter(ipaddr=ip).update(connect_alarm_num=0)
    54 
    55 
    56 # 使用多线程
    57 def start_ping(startip, endip):
    58     stip = startip.split('.')
    59     enip = endip.split('.')
    60     tmp_ip = stip
    61     a = 1
    62     pthread_list = []
    63     for i in range(int(stip[3]), int(enip[3]) + 1):
    64         tmp_ip[3] = str(i)
    65         ip = '.'.join(tmp_ip)
    66         print("多线程拼接ip是否成功"+ip)  #改为写入日志
    67         pthread_list.append(threading.Thread(target=ip_status_alarm, args=(ip,)))
    68     for item in pthread_list:
    69         # item.setDaemon(False)
    70         print("启动第几个线程:", a)  # 改为写入日志
    71         a = a + 1
    72         item.start()
    73     for item in pthread_list:
    74         item.join()
    75 
    76 # 导入Python标准库中的Thread模块
    77 # from threading import Thread
    78 # 创建一个线程,args: 线程执行方法接收的参数,该属性是一个元组,如果只有一个参数也需要在末尾加逗号。
    79 # mthread = threading.Thread(target=function_name, args=(function_parameter1, function_parameterN))
    80 # join ()方法:主线程A中,创建了子线程B,并且在主线程A中调用了B.join(),那么,主线程A会在调用的地方等待,直到子线程B完成操作后,才可以接着往下执行,那么在调用这个线程时可以使用被调用线程的join方法。
    81 # setDaemon()方法。主线程A中,创建了子线程B,并且在主线程A中调用了B.setDaemon(),这个的意思是,把主线程A设置为守护线程,这时候,要是主线程A执行结束了,就不管子线程B是否完成,一并和主线程A退出.这就是setDaemon方法的含义,这基本和join是相反的。
    82 # 此外,还有个要特别注意的:必须在start() 方法调用之前设置,如果不设置为守护线程,程序会被无限挂起。
    

    test.py

    比较啰嗦的测试代码,就不精简了。。。。

    这里使用了两种测试情况:

    ① 1.1.1.1是被定义为空闲的IP,但实际可以ping通,而且disconnect_alarm_num(无法连接天数)有残留数据的测试用例

    预期结果:connect_alarm_num(非法使用天数)+1、disconnect_alarm_num(无法连接天数)=0

    ②2.2.2.2是被定义为使用中的IP,但实际ping不通,而且connect_alarm_num(非法使用天数)有残留数据的测试用例

    预期结果:disconnect_alarm_num(无法连接天数)+1、connect_alarm_num(非法使用天数)=0

    还可以增加测试用例

    ① 3.3.3.3是被定义为空闲的IP,且实际ping不通,但connect_alarm_num(非法使用天数)有非0数据的测试用例

    预期结果:connect_alarm_num(非法使用天数)=0、disconnect_alarm_num(无法连接天数)=0

    ②4.4.4.4是被定义为使用中的IP,且实际可以ping通,但disconnect_alarm_num(无法连接天数)有残留数据的测试用例

    预期结果:disconnect_alarm_num(无法连接天数)=0、connect_alarm_num(非法使用天数)=0

    from django.test import TestCase, TransactionTestCase
    from mysiteapp import views
    from mysiteapp.models import ipaddr_info
    
    # Create your tests here.
    class start_ping_test(TransactionTestCase):
        def setUp(self):
            ipaddr_info.objects.create(ipaddr="1.1.1.1", ipstatus="0", disconnect_alarm_num=5)
            ipaddr_info.objects.create(ipaddr="2.2.2.2", ipstatus="1", connect_alarm_num=5)
            startip='1.1.1.1'
            endip='2.2.2.2'
            stip = startip.split('.')
            enip = endip.split('.')
            tmp_ip = stip
            for i in range(int(stip[3]), int(enip[3]) + 1):
                tmp_ip[3] = str(i)
                ip = '.'.join(tmp_ip)
                ipobj = ipaddr_info.objects.get(ipaddr=ip)
                print("这是开始:", ipobj.ipaddr, ipobj.ipstatus, ipobj.disconnect_alarm_num, ipobj.connect_alarm_num)
    
        def test_ping(self):
            startip = '1.1.1.1'
            endip = '2.2.2.2'
            views.start_ping(startip, endip)  #TestCase情况下,从主函数进去,调用子函数的时候查无数据
            # views.ip_status_alarm(startip)      #直接从子函数进去,才有数据
            # views.ip_status_alarm(endip)
    
        def tearDown(self):
            for item in ipaddr_info.objects.all():
                print("这是结束:", item.ipaddr, item.ipstatus, item.disconnect_alarm_num, item.connect_alarm_num)

    执行结果:

  • 相关阅读:
    unity2D动画和图片切割
    Premiere导入视频之后音频轨没有内容
    .net视频教程代码之《提交注册内容》
    搭建ftp
    Unity PC端发布失败解决办法
    Unity触发器有时失效的原因
    NGUI的UIRoot会移动
    Random类(随机数)
    Devexpress Xtrareport 打印报表
    Devexpress Xtrareports 创建多栏报表
  • 原文地址:https://www.cnblogs.com/cyanlee/p/12029395.html
Copyright © 2011-2022 走看看