zoukankan      html  css  js  c++  java
  • 运维平台cmdb开发-day2

    一 发送数据到api(Django的URL)

    发送请求携带参数

    requests.get(url='http://127.0.0.1:8000/api/asset/?k1=123')   # <QueryDict: {'k1': ['123']}>
    requests.get(url='http://127.0.0.1:8000/api/asset/',params={'k1':'v1','k2':'v2'})  # <QueryDict: {'k2': ['v2'], 'k1': ['v1']}>
    get传参
    requests.post(
        url='http://127.0.0.1:8000/api/asset/',
        params={'k1':'v1','k2':'v2'}, # GET形式传值  URL<QueryDict: {'k2': ['v2'], 'k1': ['v1']}>
        data={'username':'1123','pwd': '666'}, # POST形式传值 请求体 <QueryDict: {'pwd': ['666'], 'username': ['1123']}>
        headers={'a':'123'} # 请求头数据
    )
    requests.body   b'username=1123&pwd=666'
    post传参

    api需要post请求,并且有一定的数据格式

    # 数据格式
    host_data = {
        'status': True,
        'data':{
            'hostname': 'c1.com',
            'disk': {'status':True,'data': 'xxx'},
            'mem': {'status':True,'data': 'xxx'},
            'nic': {'status':True,'data': 'xxx'},
        }
    }
    
    # 模拟给API发送资产信息
    response = requests.post(
        url='http://127.0.0.1:8000/api/asset/',
        # 序列化
        # data=host_data,   # 列表   <QueryDict: {'data': ['nic', 'disk', 'hostname', 'mem'], 'status': ['True']}>
        json=host_data,      # reuest.body 里面 # 字典 b'{"status": true,
                                # "data": {
                                # "disk": {"status": true, "data": "xxx"},
                                # "nic": {"status": true, "data": "xxx"},
                                # "hostname": "c1.com",
                                # "mem": {"status": true, "data": "xxx"}}
                                # }'
    )
    print(response.text)   # 得到是 django执行的返回值 ...
    post序列化请求

    而我们客户端传送这样的数据格式的时候,用到了lib下的serialize,response俩个模块来对数据进行格式化

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    
    
    class BaseResponse(object):
        def __init__(self):
            self.status = True
            self.message = None
            self.data = None
            self.error = None
    response模块

    每一个资产信息都继承了response这个模块,最终得到一个对象,如下

    {
    status = True
    message = None
    data = os_platform:'',os_version:'',hostname:'','cpu':OBJ,'disk':OBJ}    这个OBJ会在交给自己写的JSON.dump去处理
    error = None
    }
    资产对象字典

    然后经过serialize模块处理

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    import json as default_json
    from json.encoder import JSONEncoder
    from .response import BaseResponse
    
    # 例子来源于本目录TEST  {"k1": 123, "k2": "2018-03-13 18", "k3": {"status": true, "data": "asdf"}}
    class JsonEncoder(JSONEncoder):
        # O 就是字典的VULe
        def default(self, o):
            if isinstance(o, BaseResponse):
                # 用O.__DICT__处理  { "k3": {"status": true, "data": "asdf"}} 字典套字典
                return o.__dict__
            # 用默认的数据类型
            return JSONEncoder.default(self, o)
    
    
    # 自己写的JSON数,JSON.DUMP 只能序列PYTHON内部数据格式,对象不行,时间对象
    class Json(object):
        @staticmethod
        def dumps(response, ensure_ascii=True): #  cls=JsonEncoder 自定义序列化
            return default_json.dumps(response, ensure_ascii=ensure_ascii, cls=JsonEncoder)
    
    
    # 传过来的是response.date,也就是说传过来的是
    '''{
    
        data = {os_platform:'',os_version:'',hostname:'','cpu':OBJ}
    
        这个OBJ是BaseResponse对象,所以格式化成
        cpu:{
            self.status = True
            self.message = None
            self.data = None
            self.error = None
            }
    }'''
    serialize模块

    这样我就拿到了一个json数据,格式如下

    {
        "disk": {
            "message": null,
            "error": null,
            "data": {
                "0": {
                    "model": "SEAGATE ST300MM0006     LS08S0K2B5NV",
                    "capacity": "279.396",
                    "pd_type": "SAS",
                    "slot": "0"
                },
                "5": {
                    "model": "S1AXNSAFB00549A     Samsung SSD 840 PRO Series              DXM06B0Q",
                    "capacity": "476.939",
                    "pd_type": "SATA",
                    "slot": "5"
                },
                "4": {
                    "model": "S1AXNSAF303909M     Samsung SSD 840 PRO Series              DXM05B0Q",
                    "capacity": "476.939",
                    "pd_type": "SATA",
                    "slot": "4"
                },
                "3": {
                    "model": "S1AXNSAF912433K     Samsung SSD 840 PRO Series              DXM06B0Q",
                    "capacity": "476.939",
                    "pd_type": "SATA",
                    "slot": "3"
                },
                "2": {
                    "model": "S1SZNSAFA01085L     Samsung SSD 850 PRO 512GB               EXM01B6Q",
                    "capacity": "476.939",
                    "pd_type": "SATA",
                    "slot": "2"
                },
                "1": {
                    "model": "SEAGATE ST300MM0006     LS08S0K2B5AH",
                    "capacity": "279.396",
                    "pd_type": "SAS",
                    "slot": "1"
                }
            },
            "status": true
        },
        "os_version": "CentOS release 6.6 (Final)",
        "os_platform": "linux",
        "hostname": "bj.com"
    }
    包含基本信息和硬盘

    api处接受到请求的处理

     if request.method == 'POST':  # GET 模式不用走这里,因为BODY 里面没有值,肯定会报错
                import json
                host_info = json.loads(str(request.body,encoding='utf-8'))
                print(host_info)
            }
        return HttpResponse('....')
    post请求处理

    二 api验证

    第一种:发送一个字符串auth_key

    1. 首先可以发送请求的时候,发过来一个验证token

    host_data = {
        'status': True,
        'data':{
            'hostname': 'c1.com',
            'disk': {'status':True,'data': 'xxx'},
            'mem': {'status':True,'data': 'xxx'},
            'nic': {'status':True,'data': 'xxx'},
        }
    }
    
    # 模拟给API发送资产信息
    response = requests.post(
        url='http://127.0.0.1:8000/api/asset/',
        # 序列化
        json=host_data, }'
        # 模拟发送个验证TOKEN
        headers={'authkey': '123456'}
    )
    print(response.text)   # 得到是 django执行的返回值 ...
    post序列化验证请求

    2. 在api处获取到这个token,进行校验,在处理post请求数据

    from django.shortcuts import render, HttpResponse
    from django.views.decorators.csrf import csrf_exempt, csrf_protect
    
    @csrf_exempt
    def asset(request):
        auth_key = request.GET.get('HTTP_AUTHKEY')
        auth_key = request.META['HTTP_AUTHKEY']  # 会存在这里面反过来的KEY
        ck = 123456
        if auth_key != ck:
            return HttpResponse('授权失败')
        if request.method == 'POST':  # GET 模式不用走这里,因为BODY 里面没有值,肯定会报错
            import json
            host_info = json.loads(str(request.body,encoding='utf-8'))
            print(host_info)
        # {'status': True,
        # 'data': {
        # 'hostname': 'c1.com',
        # 'mem': {'status': True, 'data': 'xxx'},
        # 'disk': {'status': True, 'data': 'xxx'},
        # 'nic': {'status': True, 'data': 'xxx'}}
        # }
            return HttpResponse('....')
    post验证请求处理

    存在的问题就是,有可能这个请求被截胡,很可能会被其他人获取到这个token

    第二种:md5加密字符串    很可能会被其他人获取到这个token

    ## MD5加密的验证TOKEN
    appid = '123456'
    m = hashlib.md5()
    m.update(bytes(appid,encoding='utf-8'))
    authkey = m.hexdigest()
    print(authkey)  # e10adc3949ba59abbe56e057f20f883e
    
    host_data = {
        'status': True,
        'data':{
            'hostname': 'c1.com',
            'disk': {'status':True,'data': 'xxx'},
            'mem': {'status':True,'data': 'xxx'},
            'nic': {'status':True,'data': 'xxx'},
        }
    }
    
    # 模拟给API发送资产信息
    response = requests.post(
        url='http://127.0.0.1:8000/api/asset/',
        # 序列化
        # data=host_data,   # 列表   <QueryDict: {'data': ['nic', 'disk', 'hostname', 'mem'], 'status': ['True']}>
        json=host_data,      # reuest.body 里面 # 字典 b'{"status": true,
    
        # 模拟发送个验证TOKEN
        headers={'authkey': authkey}
    )
    print(response.text)   # 得到是 django执行的返回值 ...
    post序列化请求md5字符串验证
    from django.shortcuts import render, HttpResponse
    from django.views.decorators.csrf import csrf_exempt, csrf_protect
    
    @csrf_exempt
    def asset(request):
        print(request.method)
        print(request.POST)
        print(request.GET)
        print(request.body)
        
        auth_key = request.GET.get('HTTP_AUTHKEY')
        auth_key = request.META['HTTP_AUTHKEY']  # 会存在这里面反过来的KEY
        ck = 123456
        if auth_key != ck:
            return HttpResponse('授权失败')
        if request.method == 'POST':  # GET 模式不用走这里,因为BODY 里面没有值,肯定会报错
            import json
            host_info = json.loads(str(request.body,encoding='utf-8'))
            print(host_info)
        # {'status': True,
        # 'data': {
        # 'hostname': 'c1.com',
        # 'mem': {'status': True, 'data': 'xxx'},
        # 'disk': {'status': True, 'data': 'xxx'},
        # 'nic': {'status': True, 'data': 'xxx'}}
        # }
            return HttpResponse('....')
                # 获取到的数据格式
            # request.body 内容
            # 字典 b'{"status": true,
            # "data": {
            # "disk": {"status": true, "data": "xxx"},
            # "nic": {"status": true, "data": "xxx"},
            # "hostname": "c1.com",
            # "mem": {"status": true, "data": "xxx"}}
            # }'
    post处理加密字符串认证

    第三种:md5时间动态加密字符串    漏洞更多,很可能会被其他人获取到这个token,可以访问很多的url

    # 时间动态加密
    current_time = time.time()
    app_id = "8kasoimnasodn8687asdfkmasdf"
    app_id_time = "%s|%s" %(app_id,current_time,)
    
    m = hashlib.md5()
    m.update(bytes(app_id_time,encoding='utf-8'))
    authkey = m.hexdigest()
    
    # 将加密验证TOKEN和时间带过去
    authkey_time = "%s|%s" %(authkey,current_time,)
    print(authkey_time)
    #  2746e6acc0c36f31d68dd6a166b434be|1520910092.340296
    
    
    host_data = {
        'status': True,
        'data':{
            'hostname': 'c1.com',
            'disk': {'status':True,'data': 'xxx'},
            'mem': {'status':True,'data': 'xxx'},
            'nic': {'status':True,'data': 'xxx'},
        }
    }
    
    # 模拟给API发送资产信息
    response = requests.post(
        url='http://127.0.0.1:8000/api/asset/',
        # 序列化
        json=host_data,      # reuest.body 里面 # 字典 b'{"status": true,
    
        # 模拟发送个验证TOKEN
        headers={'authkey': authkey_time}
    )
    print(response.text)     # 得到是 django执行的返回值 ...
    post序列化请求md5动态时间验证
    from django.shortcuts import render, HttpResponse
    from django.views.decorators.csrf import csrf_exempt, csrf_protect
    import hashlib
    import time
    
    ck = "8kasoimnasodn8687asdfkmasdf"
    
    auth_list = []
    
    @csrf_exempt
    def asset(request):
        # 发过来的验证TOKEN auth_key:2746e6acc0c36f31d68dd6a166b434be|client_ctime:1520910092.340296
        # 客户端发过来的时间验证
        auth_key_time = request.META['HTTP_AUTHKEY']
        auth_key_client, client_ctime = auth_key_time.split('|')
    
        # 我这里的时间验证
        key_time = "%s|%s" % (ck, client_ctime,)
        m = hashlib.md5()
        m.update(bytes(key_time, encoding='utf-8'))
        authkey = m.hexdigest()
    
        if authkey != auth_key_client:   # 判断 2次加密后的TOKEN
            return HttpResponse('授权失败')
        return HttpResponse('....')
    post处理加密时间认证

    第四种:通过时间规则限制,模仿cookie

    # 时间动态加密
    current_time = time.time()
    app_id = "8kasoimnasodn8687asdfkmasdf"
    app_id_time = "%s|%s" %(app_id,current_time,)
    
    m = hashlib.md5()
    m.update(bytes(app_id_time,encoding='utf-8'))
    authkey = m.hexdigest()
    
    # 将加密验证TOKEN和时间带过去
    authkey_time = "%s|%s" %(authkey,current_time,)
    print(authkey_time)
    #  2746e6acc0c36f31d68dd6a166b434be|1520910092.340296
    
    
    host_data = {
        'status': True,
        'data':{
            'hostname': 'c1.com',
            'disk': {'status':True,'data': 'xxx'},
            'mem': {'status':True,'data': 'xxx'},
            'nic': {'status':True,'data': 'xxx'},
        }
    }
    
    # 模拟给API发送资产信息
    response = requests.post(
        url='http://127.0.0.1:8000/api/asset/',
        # 序列化
        json=host_data,      # reuest.body 里面 # 字典 b'{"status": true,
    
        # 模拟发送个验证TOKEN
        headers={'authkey': authkey_time}
    )
    print(response.text)     # 得到是 django执行的返回值 ...
    psot序列化请求md5动态时间验证
    from django.shortcuts import render, HttpResponse
    from django.views.decorators.csrf import csrf_exempt, csrf_protect
    import hashlib
    import time
    
    ck = "8kasoimnasodn8687asdfkmasdf"
    
    # 访问时间列表,应该设置过期时间,MEMCACHE,REDIS都可以做
    auth_list = []
    
    
    @csrf_exempt
    def asset(request):
        # 发过来的验证TOKEN  客户端发过来的时间验证
        auth_key_time = request.META['HTTP_AUTHKEY']
        # auth_key_client:2746e6acc0c36f31d68dd6a166b434be | client_ctime:1520910092.340296
        auth_key_client, client_ctime = auth_key_time.split('|')
    
        # 1。时间规则 久远排除掉
        server_current_time = time.time()
        if server_current_time - 5 > float(client_ctime):
            return HttpResponse('时间太久远了')
    
        # 2。是不是来过
        if auth_key_time in auth_list:
            return HttpResponse('已经访问过了,所以你是木马')
    
        # 3。我这里的时间验证
        key_time = "%s|%s" % (ck, client_ctime,)
        m = hashlib.md5()
        m.update(bytes(key_time, encoding='utf-8'))
        authkey = m.hexdigest()
    
        if authkey != auth_key_client:
            return HttpResponse('授权失败')
        # 访问成功
        auth_list.append(auth_key_time)
        print(auth_list)
        return HttpResponse('....')
    post处理加密动态时间认证

    三 表结构

    from django.db import models
    
    
    class UserProfile(models.Model):
        """
        用户信息
        """
        name = models.CharField(u'姓名', max_length=32)
        email = models.EmailField(u'邮箱')
        phone = models.CharField(u'座机', max_length=32)
        mobile = models.CharField(u'手机', max_length=32)
    
        class Meta:
            verbose_name_plural = "用户表"
    
        def __str__(self):
            return self.name
    
    
    class AdminInfo(models.Model):
        """
        用户登陆相关信息
        """
        user_info = models.OneToOneField("UserProfile")
    
        username = models.CharField(u'用户名', max_length=64)
        password = models.CharField(u'密码', max_length=64)
    
        class Meta:
            verbose_name_plural = "管理员表"
    
        def __str__(self):
            return self.user_info.name
    
    
    class UserGroup(models.Model):
        """
        用户组
        """
        name = models.CharField(max_length=32, unique=True)
        users = models.ManyToManyField('UserProfile')
    
        class Meta:
            verbose_name_plural = "用户组表"
    
        def __str__(self):
            return self.name
    
    
    class BusinessUnit(models.Model):
        """
        业务线
        """
        name = models.CharField('业务线', max_length=64, unique=True)
        contact = models.ForeignKey('UserGroup', verbose_name='业务联系人', related_name='c') # 多个人
        manager = models.ForeignKey('UserGroup', verbose_name='系统管理员', related_name='m') # 多个人
    
        class Meta:
            verbose_name_plural = "业务线表"
    
        def __str__(self):
            return self.name
    
    
    class IDC(models.Model):
        """
        机房信息
        """
        name = models.CharField('机房', max_length=32)
        floor = models.IntegerField('楼层', default=1)
    
        class Meta:
            verbose_name_plural = "机房表"
    
        def __str__(self):
            return self.name
    
    
    class Tag(models.Model):
        """
        资产标签
        """
        name = models.CharField('标签', max_length=32, unique=True)
    
        class Meta:
            verbose_name_plural = "标签表"
    
        def __str__(self):
            return self.name
    
    
    class Asset(models.Model):
        """
        资产信息表,所有资产公共信息(交换机,服务器,防火墙等)
        """
        device_type_choices = (
            (1, '服务器'),
            (2, '交换机'),
            (3, '防火墙'),
        )
        device_status_choices = (
            (1, '上架'),
            (2, '在线'),
            (3, '离线'),
            (4, '下架'),
        )
    
        device_type_id = models.IntegerField(choices=device_type_choices, default=1)
        device_status_id = models.IntegerField(choices=device_status_choices, default=1)
    
        cabinet_num = models.CharField('机柜号', max_length=30, null=True, blank=True)
        cabinet_order = models.CharField('机柜中序号', max_length=30, null=True, blank=True)
    
        idc = models.ForeignKey('IDC', verbose_name='IDC机房', null=True, blank=True)
        business_unit = models.ForeignKey('BusinessUnit', verbose_name='属于的业务线', null=True, blank=True)
    
        tag = models.ManyToManyField('Tag')
    
        latest_date = models.DateField(null=True)
        create_at = models.DateTimeField(auto_now_add=True)
    
        class Meta:
            verbose_name_plural = "资产表"
    
        def __str__(self):
            return "%s-%s-%s" % (self.idc.name, self.cabinet_num, self.cabinet_order)
    
    
    class Server(models.Model):
        """
        服务器信息
        """
        asset = models.OneToOneField('Asset')
    
        hostname = models.CharField(max_length=128, unique=True)
        sn = models.CharField('SN号', max_length=64, db_index=True)
        manufacturer = models.CharField(verbose_name='制造商', max_length=64, null=True, blank=True)
        model = models.CharField('型号', max_length=64, null=True, blank=True)
    
        manage_ip = models.GenericIPAddressField('管理IP', null=True, blank=True)
    
        os_platform = models.CharField('系统', max_length=16, null=True, blank=True)
        os_version = models.CharField('系统版本', max_length=16, null=True, blank=True)
    
        cpu_count = models.IntegerField('CPU个数', null=True, blank=True)
        cpu_physical_count = models.IntegerField('CPU物理个数', null=True, blank=True)
        cpu_model = models.CharField('CPU型号', max_length=128, null=True, blank=True)
    
        create_at = models.DateTimeField(auto_now_add=True, blank=True)
    
        class Meta:
            verbose_name_plural = "服务器表"
    
        def __str__(self):
            return self.hostname
    
    
    class NetworkDevice(models.Model):
        asset = models.OneToOneField('Asset')
        management_ip = models.CharField('管理IP', max_length=64, blank=True, null=True)
        vlan_ip = models.CharField('VlanIP', max_length=64, blank=True, null=True)
        intranet_ip = models.CharField('内网IP', max_length=128, blank=True, null=True)
        sn = models.CharField('SN号', max_length=64, unique=True)
        manufacture = models.CharField(verbose_name=u'制造商', max_length=128, null=True, blank=True)
        model = models.CharField('型号', max_length=128, null=True, blank=True)
        port_num = models.SmallIntegerField('端口个数', null=True, blank=True)
        device_detail = models.CharField('设置详细配置', max_length=255, null=True, blank=True)
    
        class Meta:
            verbose_name_plural = "网络设备"
    
    
    class Disk(models.Model):
        """
        硬盘信息
        """
        slot = models.CharField('插槽位', max_length=8)
        model = models.CharField('磁盘型号', max_length=32)
        capacity = models.FloatField('磁盘容量GB')
        pd_type = models.CharField('磁盘类型', max_length=32)
        server_obj = models.ForeignKey('Server',related_name='disk')
    
        class Meta:
            verbose_name_plural = "硬盘表"
    
        def __str__(self):
            return self.slot
    
    
    class NIC(models.Model):
        """
        网卡信息
        """
        name = models.CharField('网卡名称', max_length=128)
        hwaddr = models.CharField('网卡mac地址', max_length=64)
        netmask = models.CharField(max_length=64)
        ipaddrs = models.CharField('ip地址', max_length=256)
        up = models.BooleanField(default=False)
        server_obj = models.ForeignKey('Server',related_name='nic')
    
    
        class Meta:
            verbose_name_plural = "网卡表"
    
        def __str__(self):
            return self.name
    
    
    class Memory(models.Model):
        """
        内存信息
        """
        slot = models.CharField('插槽位', max_length=32)
        manufacturer = models.CharField('制造商', max_length=32, null=True, blank=True)
        model = models.CharField('型号', max_length=64)
        capacity = models.FloatField('容量', null=True, blank=True)
        sn = models.CharField('内存SN号', max_length=64, null=True, blank=True)
        speed = models.CharField('速度', max_length=16, null=True, blank=True)
    
        server_obj = models.ForeignKey('Server',related_name='memory')
    
    
        class Meta:
            verbose_name_plural = "内存表"
    
        def __str__(self):
            return self.slot
    
    
    class AssetRecord(models.Model):
        """
        资产变更记录,creator为空时,表示是资产汇报的数据。
        """
        asset_obj = models.ForeignKey('Asset', related_name='ar')
        content = models.TextField(null=True)
        creator = models.ForeignKey('UserProfile', null=True, blank=True)
        create_at = models.DateTimeField(auto_now_add=True)
    
    
        class Meta:
            verbose_name_plural = "资产记录表"
    
        def __str__(self):
            return "%s-%s-%s" % (self.asset_obj.idc.name, self.asset_obj.cabinet_num, self.asset_obj.cabinet_order)
    
    
    class ErrorLog(models.Model):
        """
        错误日志,如:agent采集数据错误 或 运行错误
        """
        asset_obj = models.ForeignKey('Asset', null=True, blank=True)
        title = models.CharField(max_length=16)
        content = models.TextField()
        create_at = models.DateTimeField(auto_now_add=True)
    
        class Meta:
            verbose_name_plural = "错误日志表"
    
        def __str__(self):
            return self.title
    全部表结构设计

    表结构创建好了之后,登陆到admin添加信息

      --   用户,用户组,业务线,机房  可以提前添加

      --   数据库和收集来的资产数据对比

        新数据又,数据库没有—新增
        数据库有。新数据没有 — 拔走
        数据库也有,新数据也有,但是数据不一样 — 更新

      --   我们变更数据库信息的时候建议

        应该先有一些基本信息,然后在汇报的时候再有详细信息    资产  -  服务器(主机名,序列号...)

     四 数据库资产变更

    @method_decorator(auth.api_auth)  # 装饰器,必须执行api_auth,规则限制
        def post(self, request, *args, **kwargs):
            """
            更新或者添加资产信息
            :param request:
            :param args:
            :param kwargs:
            :return: 1000 成功;1001 接口授权失败;1002 数据库中资产不存在
            """
    
            server_info = json.loads(request.body.decode('utf-8'))
    
            server_info = json.loads(server_info)
    
            # 有一步测试,将RET返回  遇到问题。第一种新加。第二种,是不是应该先有一些基本信息,然后在汇报的时候再有详细信息 资产-服务器
            # ret = {'code': 1000, 'message': ''}
            # print(server_info)
    
            # server_info 最新汇报服务器所有信息
            hostname = server_info['hostname']
    
            ret = {'code': 1000, 'message': '[%s]更新完成' % hostname}
    
            # 根据主机名去数据库中获取相关信息
            server_obj = models.Server.objects.filter(hostname=hostname).select_related('asset').first()
    
            # 如果数据库没有这个主机,我们不录入
            if not server_obj:
                ret['code'] = 1002
                ret['message'] = '[%s]资产不存在' % hostname
                return JsonResponse(ret)
            
            
            # 数据库变更
            for k,v in config.PLUGINS_DICT.items():
                module_path,cls_name = v.rsplit('.',1)
                cls = getattr(importlib.import_module(module_path),cls_name)
                response = cls.process(server_obj,server_info,None)
                if not response.status:
                    ret['code'] = 1003
                    ret['message'] = '[%s]资产变更异常' % hostname
                if hasattr(cls,'update_last_time'):
                    cls.update_last_time(server_obj,None)
    
            # ========》 server_obj服务器对象 ;server_info  《==========
            # 硬盘 或 网卡 或 内存
            # 硬盘:增删改
            # 1. server_obj反向关联硬盘表,获取数据库中硬盘信息
            # [
            #     {'slot': "#1", 'size': '100'},
            #     {'slot': "#2", 'size': '60'},
            #     {'slot': "#3", 'size': '88'},
            # ]
            # old_list = ['#1','#2','#3']
            # 2. server_info['disk'] 新汇报的硬盘数据
            # {
            #     "#1":{'slot': "#1", 'size': '90'},
            #     "#4":{'slot': "#4", 'size': '40'},
            # }
            # new_list = ['#1','#4']
            #3. 更新['#1'] 删除['#2','#3'] 增加 ['#4']
    
            #4. # 增加 ['#4']
            """
            for i in  ['#4']:
                data_dict = dic[i]
                models.Diks.objces.create(**data_dict)
            """
    
            return JsonResponse(ret)
    post资产数据和数据库数据变更
    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    import traceback
    import datetime
    from utils.response import BaseResponse
    from utils import agorithm
    from repository import models
    
    from django.db.models import Q
    import datetime
    
    
    def get_untreated_servers():
        response = BaseResponse()
        try:
            current_date = datetime.date.today()
    
            condition = Q()
    
            # 今日未采集的资产
            con_date = Q()
            con_date.connector = 'OR'
            con_date.children.append(("asset__latest_date__lt", current_date))
            con_date.children.append(("asset__latest_date", None))
    
            # 在线状态的服务器
            con_status = Q()
            con_status.children.append(('asset__device_status_id', '2'))
    
            condition.add(con_date, 'AND')
            condition.add(con_status, 'AND')
    
            result = models.Server.objects.filter(condition).values('hostname')
            response.data = list(result)
            response.status = True
        except Exception as e:
            response.message = str(e)
            models.ErrorLog.objects.create(asset_obj=None, title='get_untreated_servers', content=traceback.format_exc())
        return response
    
    
    # ############# 操作基本信息(cpu和主板) #############
    # 操作基本,并记录操作日志
    # 更新cpu和主板信息
    class HandleBasic(object):
        # 处理基本信息,包括主板和CPU信息
        @staticmethod
        def process(server_obj, server_info, user_obj):
            response = BaseResponse()
            try:
                log_list = []
                main_board = server_info['main_board']['data']
                cpu = server_info['cpu']['data']
                if server_obj.os_platform != server_info['os_platform']:
                    log_list.append('系统由%s变更为%s' % (server_obj.os_platform, server_info['os_platform'],))
                    server_obj.os_platform = server_info['os_platform']
    
                if server_obj.os_version != server_info['os_version']:
                    log_list.append(u'系统版本由%s变更为%s' % (server_obj.os_version, server_info['os_version'],))
                    server_obj.os_version = server_info['os_version']
    
                if server_obj.sn != main_board['sn']:
                    log_list.append(u'主板SN号由%s变更为%s' % (server_obj.sn, main_board['sn'],))
                    server_obj.sn = main_board['sn']
    
                if server_obj.manufacturer != main_board['manufacturer']:
                    log_list.append(u'主板厂商由%s变更为%s' % (server_obj.manufacturer, main_board['manufacturer'],))
                    server_obj.manufacturer = main_board['manufacturer']
    
                if server_obj.model != main_board['model']:
                    log_list.append(u'主板型号由%s变更为%s' % (server_obj.model, main_board['model'],))
                    server_obj.model = main_board['model']
    
                if server_obj.cpu_count != cpu['cpu_count']:
                    log_list.append(u'CPU逻辑核数由%s变更为%s' % (server_obj.cpu_count, cpu['cpu_count'],))
                    server_obj.cpu_count = cpu['cpu_count']
    
                if server_obj.cpu_physical_count != cpu['cpu_physical_count']:
                    log_list.append(
                        u'CPU物理核数由%s变更为%s' % (server_obj.cpu_physical_count, cpu['cpu_physical_count'],))
                    server_obj.cpu_physical_count = cpu['cpu_physical_count']
    
                if server_obj.cpu_model != cpu['cpu_model']:
                    log_list.append(u'CPU型号由%s变更为%s' % (server_obj.cpu_model, cpu['cpu_model'],))
                    server_obj.cpu_model = cpu['cpu_model']
    
                server_obj.save()
                if log_list:
                    models.AssetRecord.objects.create(asset_obj=server_obj.asset, creator=user_obj,
                                                      content=';'.join(log_list))
            except Exception as e:
                response.status = False
                models.ErrorLog.objects.create(asset_obj=server_obj.asset, title='basic-run',
                                               content=traceback.format_exc())
            return response
    
        @staticmethod
        def update_last_time(server_obj, user_obj):
            response = BaseResponse()
            try:
                current_date = datetime.date.today()
                server_obj.asset.latest_date = current_date
                server_obj.asset.save()
                models.AssetRecord.objects.create(asset_obj=server_obj.asset, creator=user_obj, content='资产汇报')
            except Exception as e:
                response.status = False
                models.ErrorLog.objects.create(asset_obj=server_obj.asset, title='basic-run',
                                               content=traceback.format_exc())
    
            return response
    
    
    # ############# 操作网卡信息 #############
    # 操作网卡,并记录操作日志
    # 添加网卡
    # 删除网卡
    # 更新网卡信息
    class HandleNic(object):
        @staticmethod
        def process(server_obj, server_info, user_obj):
            response = BaseResponse()
            try:
                # 获取数据库中的所有网卡信息
                # server_info,服务器最新汇报的数据 server_info['nic']
                nic_info = server_info['nic']
                if not nic_info['status']:
                    response.status = False
                    models.ErrorLog.objects.create(asset_obj=server_obj.asset, title='nic-agent', content=nic_info['error'])
                    return response
    
                client_nic_dict = nic_info['data']
                nic_obj_list = models.NIC.objects.filter(server_obj=server_obj)
                nic_name_list = map(lambda x: x, (item.name for item in nic_obj_list))
    
                update_list = agorithm.get_intersection(set(client_nic_dict.keys()), set(nic_name_list))
                add_list = agorithm.get_exclude(client_nic_dict.keys(), update_list)
                del_list = agorithm.get_exclude(nic_name_list, update_list)
                # ==> 要删除、更新,添加
    
    
    
                HandleNic._add_nic(add_list, client_nic_dict, server_obj, user_obj)
                HandleNic._update_nic(update_list, nic_obj_list, client_nic_dict, server_obj, user_obj)
                HandleNic._del_nic(del_list, nic_obj_list, server_obj, user_obj)
    
            except Exception as e:
                response.status = False
                models.ErrorLog.objects.create(asset_obj=server_obj.asset, title='nic-run', content=traceback.format_exc())
    
            return response
    
        @staticmethod
        def _add_nic(add_list, client_nic_dict, server_obj, user_obj):
            for item in add_list:
                cur_nic_dict = client_nic_dict[item]
                cur_nic_dict['name'] = item
                log_str = '[新增网卡]{name}:mac地址为{hwaddr};状态为{up};掩码为{netmask};IP地址为{ipaddrs}'.format(**cur_nic_dict)
                cur_nic_dict['server_obj'] = server_obj
                models.NIC.objects.create(**cur_nic_dict)
                models.AssetRecord.objects.create(asset_obj=server_obj.asset, creator=user_obj, content=log_str)
    
    
        @staticmethod
        def _del_nic(del_list, nic_objs, server_obj, user_obj):
            for item in nic_objs:
                if item.name in del_list:
                    log_str = '[移除网卡]{name}:mac地址为{hwaddr};状态为{up};掩码为{netmask};IP地址为{ipaddrs}'.format(**item.__dict__)
                    item.delete()
                    models.AssetRecord.objects.create(asset_obj=server_obj.asset, creator=user_obj, content=log_str)
    
    
        @staticmethod
        def _update_nic(update_list, nic_objs, client_nic_dict, server_obj, user_obj):
    
            for item in nic_objs:
                if item.name in update_list:
                    log_list = []
    
                    new_hwaddr = client_nic_dict[item.name]['hwaddr']
                    if item.hwaddr != new_hwaddr:
                        log_list.append(u"[更新网卡]%s:mac地址由%s变更为%s" % (item.name, item.hwaddr, new_hwaddr))
                        item.hwaddr = new_hwaddr
                    new_up = client_nic_dict[item.name]['up']
                    if item.up != new_up:
                        log_list.append(u"[更新网卡]%s:状态由%s变更为%s" % (item.name, item.up, new_up))
                        item.up = new_up
    
                    new_netmask = client_nic_dict[item.name]['netmask']
                    if item.netmask != new_netmask:
                        log_list.append(u"[更新网卡]%s:掩码由%s变更为%s" % (item.name, item.netmask, new_netmask))
                        item.netmask = new_netmask
    
                    new_ipaddrs = client_nic_dict[item.name]['ipaddrs']
                    if item.ipaddrs != new_ipaddrs:
                        log_list.append(u"[更新网卡]%s:IP地址由%s变更为%s" % (item.name, item.ipaddrs, new_ipaddrs))
                        item.ipaddrs = new_ipaddrs
    
                    item.save()
                    if log_list:
                        models.AssetRecord.objects.create(asset_obj=server_obj.asset, creator=user_obj,
                                                          content=';'.join(log_list))
    
    
    # ############# 操作内存信息 #############
    # 操作内存,并记录操作日志
    # 添加内存
    # 删除内存
    # 更新内存信息
    class HandleMemory(object):
        @staticmethod
        def process(server_obj, server_info, user_obj):
            response = BaseResponse()
            try:
                mem_info = server_info['memory']
                if not mem_info['status']:
                    models.ErrorLog.objects.create(asset_obj=server_obj.asset, title='memory-agent',
                                                   content=mem_info['error'])
                    response.status = False
                    return response
    
                client_mem_dict = mem_info['data']
    
                mem_obj_list = models.Memory.objects.filter(server_obj=server_obj)
    
                mem_slots = map(lambda x: x, (item.slot for item in mem_obj_list))
    
                update_list = agorithm.get_intersection(set(client_mem_dict.keys()), set(mem_slots))
                add_list = agorithm.get_exclude(client_mem_dict.keys(), update_list)
                del_list = agorithm.get_exclude(mem_slots, update_list)
    
                HandleMemory._add_memory(add_list, client_mem_dict, server_obj, user_obj)
                HandleMemory._update_memory(update_list, mem_obj_list, client_mem_dict, server_obj, user_obj)
                HandleMemory._del_memory(del_list, mem_obj_list, server_obj, user_obj)
            except Exception as e:
                response.status = False
                models.ErrorLog.objects.create(asset_obj=server_obj.asset, title='memory-run',
                                               content=traceback.format_exc())
    
            return response
    
        @staticmethod
        def _add_memory(add_list, client_mem_dict, server_obj, user_obj):
            for item in add_list:
                cur_mem_dict = client_mem_dict[item]
                log_str = '[新增内存]插槽为{slot};容量为{capacity};类型为{model};速度为{speed};厂商为{manufacturer};SN号为{sn}'.format(
                    **cur_mem_dict)
                cur_mem_dict['server_obj'] = server_obj
                models.Memory.objects.create(**cur_mem_dict)
                models.AssetRecord.objects.create(asset_obj=server_obj.asset, creator=user_obj, content=log_str)
    
    
        @staticmethod
        def _del_memory(del_list, mem_objs, server_obj, user_obj):
            for item in mem_objs:
                if item.slot in del_list:
                    log_str = '[移除内存]插槽为{slot};容量为{capacity};类型为{model};速度为{speed};厂商为{manufacturer};SN号为{sn}'.format(
                        **item.__dict__)
                    item.delete()
                    models.AssetRecord.objects.create(asset_obj=server_obj.asset, creator=user_obj, content=log_str)
    
    
        @staticmethod
        def _update_memory(update_list, mem_objs, client_mem_dict, server_obj, user_obj):
            for item in mem_objs:
                if item.slot in update_list:
                    log_list = []
    
                    new_manufacturer = client_mem_dict[item.slot]['manufacturer']
                    if item.manufacturer != new_manufacturer:
                        log_list.append(u"[更新内存]%s:厂商由%s变更为%s" % (item.slot, item.manufacturer, new_manufacturer))
                        item.manufacturer = new_manufacturer
    
                    new_model = client_mem_dict[item.slot]['model']
                    if item.model != new_model:
                        log_list.append(u"[更新内存]%s:型号由%s变更为%s" % (item.slot, item.model, new_model))
                        item.model = new_model
    
                    new_capacity = client_mem_dict[item.slot]['capacity']
                    if item.capacity != new_capacity:
                        log_list.append(u"[更新内存]%s:容量由%s变更为%s" % (item.slot, item.capacity, new_capacity))
                        item.capacity = new_capacity
    
                    new_sn = client_mem_dict[item.slot]['sn']
                    if item.sn != new_sn:
                        log_list.append(u"[更新内存]%s:SN号由%s变更为%s" % (item.slot, item.sn, new_sn))
                        item.sn = new_sn
    
                    new_speed = client_mem_dict[item.slot]['speed']
                    if item.speed != new_speed:
                        log_list.append(u"[更新内存]%s:速度由%s变更为%s" % (item.slot, item.speed, new_speed))
                        item.speed = new_speed
    
                    item.save()
                    if log_list:
                        models.AssetRecord.objects.create(asset_obj=server_obj.asset, creator=user_obj,
                                                          content=';'.join(log_list))
    
    
    # ############# 操作硬盘信息 #############
    # 操作硬盘,并记录操作日志
    # 添加硬盘
    # 删除硬盘
    # 更新硬盘信息
    class HandleDisk(object):
        @staticmethod
        def process(server_obj, server_info, user_obj):
            response = BaseResponse()
            try:
                disk_info = server_info['disk']
                if not disk_info['status']:
                    response.status = False
                    models.ErrorLog.objects.create(asset_obj=server_obj.asset, title='disk-agent',
                                                   content=disk_info['error'])
                    return response
    
                client_disk_dict = disk_info['data']
    
                disk_obj_list = models.Disk.objects.filter(server_obj=server_obj)
    
                disk_slots = map(lambda x: x, (item.slot for item in disk_obj_list))
    
                update_list = agorithm.get_intersection(set(client_disk_dict.keys()), set(disk_slots))
                add_list = agorithm.get_exclude(client_disk_dict.keys(), update_list)
                del_list = agorithm.get_exclude(disk_slots, update_list)
    
                HandleDisk._add_disk(add_list, client_disk_dict, server_obj, user_obj)
                HandleDisk._update_disk(update_list, disk_obj_list, client_disk_dict, server_obj, user_obj)
                HandleDisk._del_disk(del_list, disk_obj_list, server_obj, user_obj)
    
            except Exception as e:
                response.status = False
                models.ErrorLog.objects.create(asset_obj=server_obj.asset, title='disk-run', content=traceback.format_exc())
            return response
    
        @staticmethod
        def _add_disk(add_list, client_disk_dict, server_obj, user_obj):
            for item in add_list:
                cur_disk_dict = client_disk_dict[item]
                log_str = '[新增硬盘]插槽为{slot};容量为{capacity};硬盘类型为{pd_type};型号为{model}'.format(**cur_disk_dict)
                cur_disk_dict['server_obj'] = server_obj
                models.Disk.objects.create(**cur_disk_dict)
                models.AssetRecord.objects.create(asset_obj=server_obj.asset, creator=user_obj, content=log_str)
    
    
        @staticmethod
        def _del_disk(del_list, disk_objs, server_obj, user_obj):
            for item in disk_objs:
                if item.slot in del_list:
                    log_str = '[移除硬盘]插槽为{slot};容量为{capacity};硬盘类型为{pd_type};型号为{model}'.format(**item.__dict__)
                    item.delete()
                    models.AssetRecord.objects.create(asset_obj=server_obj.asset, creator=user_obj, content=log_str)
    
    
        @staticmethod
        def _update_disk(update_list, disk_objs, client_disk_dict, server_obj, user_obj):
            for item in disk_objs:
                if item.slot in update_list:
                    log_list = []
    
                    new_model = client_disk_dict[item.slot]['model']
                    if item.model != new_model:
                        log_list.append(u"[更新硬盘]插槽为%s:型号由%s变更为%s" % (item.slot, item.model, new_model))
                        item.model = new_model
    
                    new_capacity = client_disk_dict[item.slot]['capacity']
                    new_capacity = float(new_capacity)
                    if item.capacity != new_capacity:
                        log_list.append(u"[更新硬盘]插槽为%s:容量由%s变更为%s" % (item.slot, item.capacity, new_capacity))
                        item.capacity = new_capacity
    
                    new_pd_type = client_disk_dict[item.slot]['pd_type']
                    if item.pd_type != new_pd_type:
                        log_list.append(u"[更新硬盘]插槽为%s:硬盘类型由%s变更为%s" % (item.slot, item.pd_type, new_pd_type))
                        item.pd_type = new_pd_type
    
                    item.save()
                    if log_list:
                        models.AssetRecord.objects.create(asset_obj=server_obj.asset, creator=user_obj,
                                                          content=';'.join(log_list))
    各个资产的增删改查
  • 相关阅读:
    gdb
    wine
    xen
    编程都是人上人,果不其然!2020年度十大高薪岗位,程序员独领风骚!
    【C++学习笔记】深入了解C++ 结构体与共用体,看这篇就够了!
    谁说C语言很简单?这14道C语言谜题,简直难哭了...
    十行代码15个 bug!程序员:不知道有句话当讲不当讲?
    【C++学习笔记】C++ 使用new与delete时,你注意到这3个地方了吗?
    【C++学习笔记】一分钟带你了解C++中new和delete的使用方法!
    惊!黄道十二宫杀手密码,半个世纪未解之谜,竟然被他们破解了...
  • 原文地址:https://www.cnblogs.com/jokerbj/p/8553306.html
Copyright © 2011-2022 走看看