運維平臺cmdb開發-day2

一 發送數據到api(Django的URL)

發送請求攜帶參數python

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請求,而且有必定的數據格式linux

# 數據格式
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這個模塊,最終獲得一個對象,以下django

{
status = True
message = None
data = os_platform:'',os_version:'',hostname:'','cpu':OBJ,'disk':OBJ}    這個OBJ會在交給本身寫的JSON.dump去處理
error = None
}
資產對象字典

而後通過serialize模塊處理json

#!/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數據,格式以下api

{
    "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_keycookie

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請求數據app

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))
各個資產的增刪改查
相關文章
相關標籤/搜索