cmdb資產管理2

 

新增資產

如今api服務端已經能獲取到咱們要作的操做了。接下來應該是補充獲取操做後對應的程序編寫linux

咱們要作的是把post請求發過來的數據保存到數據庫。咱們建立repository 名字的app,並設計models建立表來存儲數據。後面能夠從數據庫獲取信息並展現出來數據庫

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

咱們能夠將業務線先設置成這個。而後執行命令生成表django

咱們先將cert刪除,而且將這裏寫入文件的註釋掉,這樣每次判斷都是新增主機了json

服務端接收的數據以下圖,將它存入數據庫api

咱們要將新增的這些資產信息存入數據庫服務器

先看新增server,1處有默認,2處能夠爲空,咱們先無論數據結構

咱們先看這三種硬件信息app

而這三種硬件信息和咱們傳過來的數據一致,字段名字也同樣ide

咱們將數據字典取出來,而後update到同一個字典中,合成一個。函數

得到以下的字典

{
    '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對象的命令,將這個字典打散存入數據庫

再看看新增硬盤,硬盤是一個槽位是一個硬盤,前面新增一臺server,已經有了這臺server對象了,因此硬盤所屬外鍵server=server。for循環外層字典的值,而後將每一個內層字典打散插入到Disk數據表中。

這樣就保存了6個槽位的硬盤

這裏for循環插入數據,插入一次鏈接一次數據庫,咱們能夠進行優化一下

 for循環建立Disk對象並追加到列表。bulk_create方法根據對象列表一次批量建立數據表記錄

新增內存和新增硬盤同樣

出問題了,由於數據結構內存和網卡沒有修改,沒有保存進去

修改後點擊執行客戶端,客戶端採集信息發送給api而後保存到數據庫

而新增網卡有點區別,它以name爲鍵可是數據裏沒有name,

因此建立要將name加進去,循環並取出它的鍵加到數據庫中

 

更新資產

 咱們建立cert,將主機名和咱們固定採集的主機名一致,這樣走的就是更新資產信息了

api服務端走的是更新資產信息,服務端要寫的更新程序以下

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

下面我將主機表修改一下,執行客戶端程序後又更新回來了

如今咱們將數據庫修改以下:

由於每次提交這裏都是提交0-5的,因此新增,更新,刪除就會如上

新增,刪除和更新以下。新增是採集的減數據庫的(採集的多出來的),刪除是數據庫的減採集的(數據庫多出來的),更新是採集的和數據庫都有的(用&集合運算)。這樣獲取到槽位信息,根據槽位信息對這條記錄作相應的操做。

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

當客戶端執行採集並彙報後,服務端顯然作了對應的硬盤更新

觀察內存和網卡的程序是類似的,只是名字有點區別,能夠用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文件內容改變,讓它和會採集到的信息不一致,這樣程序就會走更新主機名和資產信息

{
    '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

而提交過來的數據裏面,還有老主機名,也就是文件裏保存的主機名

所以服務端能從發送過來的info數據獲取到主機名,從而從數據庫查到這臺服務器的信息,由於更新資產信息部分和以前寫的單純地更新資產信息部分是同樣的。

這部分咱們不用重複寫了,因此直接在app裏建立service模塊寫成函數進行調用。

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

而後咱們導入這四個類並調用。這樣就實現了更新資產信息了。

至於客戶端主機名的修改,只須要將客戶端這裏的註釋去掉就能夠了

 

 

api驗證

相關文章
相關標籤/搜索