新增資産
現在api服務端已經能擷取到我們要做的操作了。接下來應該是補充擷取操作後對應的程式編寫
我們要做的是把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
我們可以将業務線先設定成這個。然後執行指令生成表
我們先将cert删除,并且将這裡寫入檔案的注釋掉,這樣每次判斷都是新增主機了
服務端接收的資料如下圖,将它存入資料庫
我們要将新增的這些資産資訊存入資料庫
先看新增server,1處有預設,2處可以為空,我們先不管
我們先看這三種硬體資訊
而這三種硬體資訊和我們傳過來的資料一緻,字段名字也一樣
我們将資料字典取出來,然後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
然後我們導入這四個類并調用。這樣就實作了更新資産資訊了。
至于用戶端主機名的修改,隻需要将用戶端這裡的注釋去掉就可以了