天天看點

cmdb資産管理2

新增資産

現在api服務端已經能擷取到我們要做的操作了。接下來應該是補充擷取操作後對應的程式編寫

cmdb資産管理2

我們要做的是把post請求發過來的資料儲存到資料庫。我們建立repository 名字的app,并設計models建立表來存儲資料。後面可以從資料庫擷取資訊并展示出來

cmdb資産管理2
cmdb資産管理2
from django.db import models


class BusinessUnit(models.Model):
    """
    業務線
    """
    name = models.CharField('業務線', max_length=64, unique=True)

    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 Server(models.Model):
    """
    伺服器資訊 主機
    """

    device_status_choices = (
        (1, '上架'),
        (2, '線上'),
        (3, '離線'),
        (4, '下架'),
    )
    device_status_id = models.IntegerField('裝置狀态', choices=device_status_choices, default=1)

    idc = models.ForeignKey('IDC', verbose_name='IDC機房', null=True, blank=True, on_delete=models.CASCADE)
    cabinet_num = models.CharField('機櫃号', max_length=30, null=True, blank=True)
    cabinet_order = models.CharField('機櫃中序号', max_length=30, null=True, blank=True)

    business_unit = models.ForeignKey('BusinessUnit', verbose_name='屬于的業務線', null=True, blank=True,
                                      on_delete=models.CASCADE)

    # 基本資訊 + 主機闆資訊 + CPU資訊
    hostname = models.CharField('主機名', max_length=128, unique=True)
    os_platform = models.CharField('系統', max_length=16, null=True, blank=True)
    os_version = models.CharField('系統版本', max_length=16, null=True, blank=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)

    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)

    latest_date = models.DateField('最後更新時間', null=True)
    create_at = models.DateTimeField(auto_now_add=True, blank=True)

    class Meta:
        verbose_name_plural = "伺服器表"

    def __str__(self):
        return self.hostname


class Disk(models.Model):
    """
    硬碟資訊
    """
    slot = models.CharField('插槽位', max_length=8)
    model = models.CharField('磁盤型号', max_length=108)
    capacity = models.FloatField('磁盤容量GB')
    pd_type = models.CharField('磁盤類型', max_length=32)

    server = models.ForeignKey(verbose_name='伺服器', to='Server', related_name='disk_list', on_delete=models.CASCADE)

    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 = models.ForeignKey('Server', related_name='nic_list', on_delete=models.CASCADE)

    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 = models.ForeignKey('Server', related_name='memory_list', on_delete=models.CASCADE)

    class Meta:
        verbose_name_plural = "記憶體表"

    def __str__(self):
        return self.slot


class AssetRecord(models.Model):
    """
    資産變更記錄
    """
    server = models.ForeignKey('Server', related_name='servers', on_delete=models.CASCADE)
    content = models.TextField(null=True)
    create_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        verbose_name_plural = "資産記錄表"


class ErrorLog(models.Model):
    """
    錯誤日志,如:agent采集資料錯誤 或 運作錯誤
    """
    server = models.ForeignKey('Server', null=True, blank=True, on_delete=models.CASCADE)
    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      

models.py

我們可以将業務線先設定成這個。然後執行指令生成表

cmdb資産管理2

我們先将cert删除,并且将這裡寫入檔案的注釋掉,這樣每次判斷都是新增主機了

cmdb資産管理2

服務端接收的資料如下圖,将它存入資料庫

cmdb資産管理2

我們要将新增的這些資産資訊存入資料庫

cmdb資産管理2

先看新增server,1處有預設,2處可以為空,我們先不管

cmdb資産管理2

我們先看這三種硬體資訊

cmdb資産管理2

而這三種硬體資訊和我們傳過來的資料一緻,字段名字也一樣

cmdb資産管理2

我們将資料字典取出來,然後update到同一個字典中,合成一個。

cmdb資産管理2

獲得如下的字典

{
    'os_platform': 'linux',
    'os_version': '6.5',
    'hostname': 'c1.com',
    'manufacturer': 'Parallels Software International Inc.',
    'model': 'Parallels Virtual Platform',
    'sn': 'Parallels-1A 1B CB 3B 64 66 4B 13 86 B0 86 FF 7E 2B 20 30',
    'cpu_count': 24,
    'cpu_physical_count': 2,
    'cpu_model': ' Intel(R) Xeon(R) CPU E5-2620 v2 @ 2.10GHz'
}      

 然後執行建立orm對象的指令,将這個字典打散存入資料庫

cmdb資産管理2

再看看新增硬碟,硬碟是一個槽位是一個硬碟,前面新增一台server,已經有了這台server對象了,是以硬碟所屬外鍵server=server。for循環外層字典的值,然後将每個内層字典打散插入到Disk資料表中。

cmdb資産管理2

這樣就儲存了6個槽位的硬碟

cmdb資産管理2

這裡for循環插入資料,插入一次連接配接一次資料庫,我們可以進行優化一下

cmdb資産管理2

 for循環建立Disk對象并追加到清單。bulk_create方法根據對象清單一次批量建立資料表記錄

cmdb資産管理2

新增記憶體和新增硬碟一樣

cmdb資産管理2

出問題了,因為資料結構記憶體和網卡沒有修改,沒有儲存進去

cmdb資産管理2

修改後點選執行用戶端,用戶端采集資訊發送給api然後儲存到資料庫

cmdb資産管理2

而新增網卡有點差別,它以name為鍵但是資料裡沒有name,

cmdb資産管理2

是以建立要将name加進去,循環并取出它的鍵加到資料庫中

cmdb資産管理2

更新資産

 我們建立cert,将主機名和我們固定采集的主機名一緻,這樣走的就是更新資産資訊了

cmdb資産管理2

api服務端走的是更新資産資訊,服務端要寫的更新程式如下

cmdb資産管理2

下面看一下更新主機表的程式

cmdb資産管理2

下面我将主機表修改一下,執行用戶端程式後又更新回來了

cmdb資産管理2
cmdb資産管理2

現在我們将資料庫修改如下:

cmdb資産管理2

因為每次送出這裡都是送出0-5的,是以新增,更新,删除就會如上

cmdb資産管理2

新增,删除和更新如下。新增是采集的減資料庫的(采集的多出來的),删除是資料庫的減采集的(資料庫多出來的),更新是采集的和資料庫都有的(用&集合運算)。這樣擷取到槽位資訊,根據槽位資訊對這條記錄做相應的操作。

cmdb資産管理2

下面根據擷取到要做這三個操作的硬碟槽位,對它們做對應的操作

cmdb資産管理2

當用戶端執行采集并彙報後,服務端顯然做了對應的硬碟更新

cmdb資産管理2

觀察記憶體和網卡的程式是相似的,隻是名字有點差別,可以用notepad++替換,然後将有差別的地方更改正确,這樣就完成記憶體和網卡的更新操作

# 更新記憶體
    memory_info = info['memory']['data']  # 新送出的資料

    memory_slot_set = set(memory_info)
    memory_slot__db_set = {i.slot for i in models.Memory.objects.filter(server=server)}

    # 新增  删除  更新
    add_slot_set = memory_slot_set - memory_slot__db_set  # 新增的槽位
    del_slot_set = memory_slot__db_set - memory_slot_set  # 删除的槽位
    update_slot_set = memory_slot__db_set & memory_slot_set  # 更新的槽位

    # 新增記憶體

    add_memory_lit = []
    for slot in add_slot_set:
        memory = memory_info.get(slot)
        add_memory_lit.append(models.Memory(**memory, server=server))

    if add_memory_lit:
        models.Memory.objects.bulk_create(add_memory_lit)

    # 删除記憶體
    if del_slot_set:
        models.Memory.objects.filter(server=server, slot__in=del_slot_set).delete()

    # 更新記憶體
    for slot in update_slot_set:
        memory = memory_info.get(slot)
        models.Memory.objects.filter(server=server, slot=slot).update(**memory)      
nic_info = info['nic']['data']  # 新送出的資料

    nic_name_set = set(nic_info)
    nic_name__db_set = {i.name for i in models.NIC.objects.filter(server=server)}

    # 新增  删除  更新
    add_name_set = nic_name_set - nic_name__db_set  # 新增的槽位
    del_name_set = nic_name__db_set - nic_name_set  # 删除的槽位
    update_name_set = nic_name__db_set & nic_name_set  # 更新的槽位

    # 新增網卡

    add_nic_lit = []
    for name in add_name_set:
        nic = nic_info.get(name)
        nic['name'] = name
        add_nic_lit.append(models.NIC(**nic, server=server))

    if add_nic_lit:
        models.NIC.objects.bulk_create(add_nic_lit)

    # 删除網卡
    if del_name_set:
        models.NIC.objects.filter(server=server, name__in=del_name_set).delete()

    # 更新網卡
    for name in update_name_set:
        nic = nic_info.get(name)
        nic['name'] = name
        models.NIC.objects.filter(server=server, name=name).update(**nic)      

更新資産+主機名

我們在用戶端将cert檔案内容改變,讓它和會采集到的資訊不一緻,這樣程式就會走更新主機名和資産資訊

cmdb資産管理2
cmdb資産管理2
cmdb資産管理2
cmdb資産管理2
{
    'disk': {
        'status': True,
        'error': '',
        'data': {
            '0': {
                'slot': '0',
                'pd_type': 'SAS',
                'capacity': '279.396',
                'model': 'SEAGATE ST300MM0006     LS08S0K2B5NV'
            },
            '1': {
                'slot': '1',
                'pd_type': 'SAS',
                'capacity': '279.396',
                'model': 'SEAGATE ST300MM0006     LS08S0K2B5AH'
            },
            '2': {
                'slot': '2',
                'pd_type': 'SATA',
                'capacity': '476.939',
                'model': 'S1SZNSAFA01085L     Samsung SSD 850 PRO 512GB               EXM01B6Q'
            },
            '3': {
                'slot': '3',
                'pd_type': 'SATA',
                'capacity': '476.939',
                'model': 'S1AXNSAF912433K     Samsung SSD 840 PRO Series              DXM06B0Q'
            },
            '4': {
                'slot': '4',
                'pd_type': 'SATA',
                'capacity': '476.939',
                'model': 'S1AXNSAF303909M     Samsung SSD 840 PRO Series              DXM05B0Q'
            },
            '5': {
                'slot': '5',
                'pd_type': 'SATA',
                'capacity': '476.939',
                'model': 'S1AXNSAFB00549A     Samsung SSD 840 PRO Series              DXM06B0Q'
            }
        }
    },
    'memory': {
        'status': True,
        'error': '',
        'data': {
            'DIMM #0': {
                'capacity': 1024,
                'slot': 'DIMM #0',
                'model': 'DRAM',
                'speed': '667 MHz',
                'manufacturer': 'Not Specified',
                'sn': 'Not Specified'
            },
            'DIMM #1': {
                'capacity': 0,
                'slot': 'DIMM #1',
                'model': 'DRAM',
                'speed': '667 MHz',
                'manufacturer': 'Not Specified',
                'sn': 'Not Specified'
            },
            'DIMM #2': {
                'capacity': 0,
                'slot': 'DIMM #2',
                'model': 'DRAM',
                'speed': '667 MHz',
                'manufacturer': 'Not Specified',
                'sn': 'Not Specified'
            },
            'DIMM #3': {
                'capacity': 0,
                'slot': 'DIMM #3',
                'model': 'DRAM',
                'speed': '667 MHz',
                'manufacturer': 'Not Specified',
                'sn': 'Not Specified'
            },
            'DIMM #4': {
                'capacity': 0,
                'slot': 'DIMM #4',
                'model': 'DRAM',
                'speed': '667 MHz',
                'manufacturer': 'Not Specified',
                'sn': 'Not Specified'
            },
            'DIMM #5': {
                'capacity': 0,
                'slot': 'DIMM #5',
                'model': 'DRAM',
                'speed': '667 MHz',
                'manufacturer': 'Not Specified',
                'sn': 'Not Specified'
            },
            'DIMM #6': {
                'capacity': 0,
                'slot': 'DIMM #6',
                'model': 'DRAM',
                'speed': '667 MHz',
                'manufacturer': 'Not Specified',
                'sn': 'Not Specified'
            },
            'DIMM #7': {
                'capacity': 0,
                'slot': 'DIMM #7',
                'model': 'DRAM',
                'speed': '667 MHz',
                'manufacturer': 'Not Specified',
                'sn': 'Not Specified'
            }
        }
    },
    'nic': {
        'status': True,
        'error': '',
        'data': {
            'eth0': {
                'up': True,
                'hwaddr': '00:1c:42:a5:57:7a',
                'ipaddrs': '10.211.55.4',
                'netmask': '255.255.255.0'
            }
        }
    },
    'basic': {
        'status': True,
        'error': '',
        'data': {
            'os_platform': 'linux',
            'os_version': '6.5',
            'hostname': 'c1.com'
        }
    },
    'cpu': {
        'status': True,
        'error': '',
        'data': {
            'cpu_count': 24,
            'cpu_physical_count': 2,
            'cpu_model': ' Intel(R) Xeon(R) CPU E5-2620 v2 @ 2.10GHz'
        }
    },
    'main_board': {
        'status': True,
        'error': '',
        'data': {
            'manufacturer': 'Parallels Software International Inc.',
            'model': 'Parallels Virtual Platform',
            'sn': 'Parallels-1A 1B CB 3B 64 66 4B 13 86 B0 86 FF 7E 2B 20 30'
        }
    },
    'action': 'update_host',
    'old_hostname': 'c2.com'
}      

data.json

而送出過來的資料裡面,還有老主機名,也就是檔案裡儲存的主機名

cmdb資産管理2
cmdb資産管理2

是以服務端能從發送過來的info資料擷取到主機名,進而從資料庫查到這台伺服器的資訊,因為更新資産資訊部分和之前寫的單純地更新資産資訊部分是一樣的。

cmdb資産管理2

這部分我們不用重複寫了,是以直接在app裡建立service子產品寫成函數進行調用。

cmdb資産管理2
cmdb資産管理2
from repository import models


def process_basic(info):
    server_info = {}

    basic = info['basic']['data']
    main_board = info['main_board']['data']
    cpu = info['cpu']['data']
    server_info.update(basic)
    server_info.update(main_board)
    server_info.update(cpu)

    hostname = info['basic']['data']['hostname']  # 新的hostname
    old_hostname = info.get('old_hostname')  # 老的hostname

    server_list = models.Server.objects.filter(hostname=old_hostname if old_hostname else hostname)
    server_list.update(**server_info)
    server = models.Server.objects.filter(hostname=hostname).first()
    return server


def process_disk(info, server):
    disk_info = info['disk']['data']  # 新送出的資料

    disk_slot_set = set(disk_info)
    disk_slot__db_set = {i.slot for i in models.Disk.objects.filter(server=server)}

    # 新增  删除  更新 
    add_slot_set = disk_slot_set - disk_slot__db_set  # 新增的槽位     添加硬碟
    del_slot_set = disk_slot__db_set - disk_slot_set  # 删除的槽位     減少硬碟
    update_slot_set = disk_slot__db_set & disk_slot_set  # 更新的槽位  更換硬碟

    # 新增硬碟

    add_disk_lit = []
    for slot in add_slot_set:
        disk = disk_info.get(slot)
        add_disk_lit.append(models.Disk(**disk, server=server))

    if add_disk_lit:
        models.Disk.objects.bulk_create(add_disk_lit)

    # 删除硬碟
    if del_slot_set:
        models.Disk.objects.filter(server=server, slot__in=del_slot_set).delete()

    # 更新硬碟
    for slot in update_slot_set:
        disk = disk_info.get(slot)
        models.Disk.objects.filter(server=server, slot=slot).update(**disk)


def process_memory(info, server):
    # 更新記憶體
    memory_info = info['memory']['data']  # 新送出的資料

    memory_slot_set = set(memory_info)
    memory_slot__db_set = {i.slot for i in models.Memory.objects.filter(server=server)}

    # 新增  删除  更新
    add_slot_set = memory_slot_set - memory_slot__db_set  # 新增的槽位
    del_slot_set = memory_slot__db_set - memory_slot_set  # 删除的槽位
    update_slot_set = memory_slot__db_set & memory_slot_set  # 更新的槽位

    # 新增記憶體

    add_memory_lit = []
    for slot in add_slot_set:
        memory = memory_info.get(slot)
        add_memory_lit.append(models.Memory(**memory, server=server))

    if add_memory_lit:
        models.Memory.objects.bulk_create(add_memory_lit)

    # 删除記憶體
    if del_slot_set:
        models.Memory.objects.filter(server=server, slot__in=del_slot_set).delete()

    # 更新記憶體
    for slot in update_slot_set:
        memory = memory_info.get(slot)
        models.Memory.objects.filter(server=server, slot=slot).update(**memory)


def process_nic(info, server):
    nic_info = info['nic']['data']  # 新送出的資料

    nic_name_set = set(nic_info)
    nic_name__db_set = {i.name for i in models.NIC.objects.filter(server=server)}

    # 新增  删除  更新
    add_name_set = nic_name_set - nic_name__db_set  # 新增的槽位
    del_name_set = nic_name__db_set - nic_name_set  # 删除的槽位
    update_name_set = nic_name__db_set & nic_name_set  # 更新的槽位

    # 新增網卡

    add_nic_lit = []
    for name in add_name_set:
        nic = nic_info.get(name)
        nic['name'] = name
        add_nic_lit.append(models.NIC(**nic, server=server))

    if add_nic_lit:
        models.NIC.objects.bulk_create(add_nic_lit)

    # 删除網卡
    if del_name_set:
        models.NIC.objects.filter(server=server, name__in=del_name_set).delete()

    # 更新網卡
    for name in update_name_set:
        nic = nic_info.get(name)
        nic['name'] = name
        models.NIC.objects.filter(server=server, name=name).update(**nic)      

service.py

然後我們導入這四個類并調用。這樣就實作了更新資産資訊了。

cmdb資産管理2

至于用戶端主機名的修改,隻需要将用戶端這裡的注釋去掉就可以了

cmdb資産管理2

api驗證