cmdb资产管理2
新增资产
现在api服务端已经能获取到我们要做的操作了。接下来应该是补充获取操作后对应的程序编写

我们要做的是把post请求发过来的数据保存到数据库。我们创建repository 名字的app,并设计models创建表来存储数据。后面可以从数据库获取信息并展示出来
from django.db import models class BusinessUnit(models.Model):
"""
业务线
"""
name = models.CharField('业务线', max_length=, unique=True) class Meta:
verbose_name_plural = "业务线表" def __str__(self):
return self.name class IDC(models.Model):
"""
机房信息
"""
name = models.CharField('机房', max_length=)
floor = models.IntegerField('楼层', default=) class Meta:
verbose_name_plural = "机房表" def __str__(self):
return self.name class Server(models.Model):
"""
服务器信息 主机
""" device_status_choices = (
(, '上架'),
(, '在线'),
(, '离线'),
(, '下架'),
)
device_status_id = models.IntegerField('设备状态', choices=device_status_choices, default=) idc = models.ForeignKey('IDC', verbose_name='IDC机房', null=True, blank=True, on_delete=models.CASCADE)
cabinet_num = models.CharField('机柜号', max_length=, null=True, blank=True)
cabinet_order = models.CharField('机柜中序号', max_length=, 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=, unique=True)
os_platform = models.CharField('系统', max_length=, null=True, blank=True)
os_version = models.CharField('系统版本', max_length=, null=True, blank=True) sn = models.CharField('SN号', max_length=, db_index=True)
manufacturer = models.CharField(verbose_name='制造商', max_length=, null=True, blank=True)
model = models.CharField('型号', max_length=, 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=, 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=)
model = models.CharField('磁盘型号', max_length=)
capacity = models.FloatField('磁盘容量GB')
pd_type = models.CharField('磁盘类型', max_length=) 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=)
hwaddr = models.CharField('网卡mac地址', max_length=)
netmask = models.CharField(max_length=)
ipaddrs = models.CharField('ip地址', max_length=)
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=)
manufacturer = models.CharField('制造商', max_length=, null=True, blank=True)
model = models.CharField('型号', max_length=)
capacity = models.FloatField('容量', null=True, blank=True)
sn = models.CharField('内存SN号', max_length=, null=True, blank=True)
speed = models.CharField('速度', max_length=, 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=)
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': ,
'cpu_physical_count': ,
'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': {
'': {
'slot': '',
'pd_type': 'SAS',
'capacity': '279.396',
'model': 'SEAGATE ST300MM0006 LS08S0K2B5NV'
},
'': {
'slot': '',
'pd_type': 'SAS',
'capacity': '279.396',
'model': 'SEAGATE ST300MM0006 LS08S0K2B5AH'
},
'': {
'slot': '',
'pd_type': 'SATA',
'capacity': '476.939',
'model': 'S1SZNSAFA01085L Samsung SSD 850 PRO 512GB EXM01B6Q'
},
'': {
'slot': '',
'pd_type': 'SATA',
'capacity': '476.939',
'model': 'S1AXNSAF912433K Samsung SSD 840 PRO Series DXM06B0Q'
},
'': {
'slot': '',
'pd_type': 'SATA',
'capacity': '476.939',
'model': 'S1AXNSAF303909M Samsung SSD 840 PRO Series DXM05B0Q'
},
'': {
'slot': '',
'pd_type': 'SATA',
'capacity': '476.939',
'model': 'S1AXNSAFB00549A Samsung SSD 840 PRO Series DXM06B0Q'
}
}
},
'memory': {
'status': True,
'error': '',
'data': {
'DIMM #0': {
'capacity': ,
'slot': 'DIMM #0',
'model': 'DRAM',
'speed': '667 MHz',
'manufacturer': 'Not Specified',
'sn': 'Not Specified'
},
'DIMM #1': {
'capacity': ,
'slot': 'DIMM #1',
'model': 'DRAM',
'speed': '667 MHz',
'manufacturer': 'Not Specified',
'sn': 'Not Specified'
},
'DIMM #2': {
'capacity': ,
'slot': 'DIMM #2',
'model': 'DRAM',
'speed': '667 MHz',
'manufacturer': 'Not Specified',
'sn': 'Not Specified'
},
'DIMM #3': {
'capacity': ,
'slot': 'DIMM #3',
'model': 'DRAM',
'speed': '667 MHz',
'manufacturer': 'Not Specified',
'sn': 'Not Specified'
},
'DIMM #4': {
'capacity': ,
'slot': 'DIMM #4',
'model': 'DRAM',
'speed': '667 MHz',
'manufacturer': 'Not Specified',
'sn': 'Not Specified'
},
'DIMM #5': {
'capacity': ,
'slot': 'DIMM #5',
'model': 'DRAM',
'speed': '667 MHz',
'manufacturer': 'Not Specified',
'sn': 'Not Specified'
},
'DIMM #6': {
'capacity': ,
'slot': 'DIMM #6',
'model': 'DRAM',
'speed': '667 MHz',
'manufacturer': 'Not Specified',
'sn': 'Not Specified'
},
'DIMM #7': {
'capacity': ,
'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': ,
'cpu_physical_count': ,
'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验证
cmdb资产管理2的更多相关文章
- CMDB资产管理
.传统运维和自动化运维的区别: 传统运维: 1.项目上线: a.产品经理前期调研(需求分析) b.和开发进行评审 c.开发进行开发 d.测试进行测试 e.交给运维人员进行上线 上线: 直接将代码交给运 ...
- Python学习路程CMDB
本节内容 浅谈ITIL CMDB介绍 Django自定义用户认证 Restful 规范 资产管理功能开发 浅谈ITIL TIL即IT基础架构库(Information Technology Infra ...
- 构建CMDB的一些启发
开篇感言: 自从学习python自动化开发以来,一直都是从技术的角度来看待一切.以为技术就是王道.但显然我是一只井底之蛙.其实技术只不过是实现功能的工具而已,仅此而已.后来学习了解CMDB,越来越发现 ...
- Python之路,Day19 - CMDB、CMDB、CMDB
Python之路,Day19 - CMDB.CMDB.CMDB 本节内容 浅谈ITIL CMDB介绍 Django自定义用户认证 Restful 规范 资产管理功能开发 浅谈ITIL TIL即IT ...
- python运维开发(二十五)---cmdb开发
内容目录: 浅谈ITIL CMDB介绍 Django自定义用户认证 Restful 规范 资产管理功能开发 浅谈ITIL TIL即IT基础架构库(Information Technology Infr ...
- Django:之CMDB资源系统
渐谈CMDB需要内容,ITIL.CMDB介绍.Django自定义用户认证.Restful规范.资产管理功能开发. ITIL介绍 TIL即IT基础架构库(Information Technology I ...
- CMDB运维开发项目
ITIL:Information Technology Infrastructure Library 信息技术基础架构库,主要适用于IT服务管理(ITSM).ITIL为企业的IT服务管理实践提供了一个 ...
- CMDB项目开发
CMDB介绍 CMDB --Configuration Management Database 配置管理数据库, CMDB存储与管理企业IT架构中设备的各种配置信息,它与所有服务支持和服务交付流程都紧 ...
- CMDB资产管理系统开发【day25】:需求分析
本节内容 浅谈ITIL CMDB介绍 Django自定义用户认证 Restful 规范 资产管理功能开发 浅谈ITIL TIL即IT基础架构库(Information Technology Infra ...
随机推荐
- Airflow使用指南
1.只执行单个任务 将downstream和recursive按钮的点击状态取消,然后点击clear,最后点击run
- Jenkins集成TestNG
1.Jenkins安装插件 TestNG Results Plugin 2. 添加配置 “构建后操作”->“Publish TestNG Results” 保持默认配置即可 3.查看报告 项目构 ...
- Maven多模块工程打包指定模块工程方法
Maven多模块工程打包指定模块工程执行如下命令: mvn clean package -pl 指定模块工程名 -am 参数说明: -am --also-make 同时构建所列模块的依赖模块:-am ...
- K8S使用入门-添加一个node
上一篇博客我们已经将K8S部署起来了,现在我们就来介绍一下如何简单使用K8S (1)添加节点 注意事项:不能和k8s master节点的主机名一样.否则会导致k8s无法正常识别出该节点 添加节点是比较 ...
- Git 克隆
工作中大家分工协作,共同开发维护一个项目,git仓库放在公共的服务器上,如github.Gitee等. 在这种情况使用git,需要先克隆仓库到本地. 克隆非常简单,使用命令git clone 将远程仓 ...
- React 的高级用法(Children、Component、createElement、cloneElement)
React.Children props.children 代表了所有的子节点. React.Children 用于处理 props.children 的 提供了几个方法 ( map ,foreach ...
- day04——列表、元组、range
day04 列表 列表--list 有序,可变,支持索引 列表:存储数据,支持的数据类型很多:字符串,数字,布尔值,列表,集合,元组,字典,用逗号分割的是一个元素 id() :获取对象的内存地址 ...
- DS AVL树详解
先说说二叉搜索树: 是有序的二叉树,根值>左节点值,右节点值>根值. 如果要查找某个值,二叉搜索树和二分查找一样,每进行一次值比较,就会减少一半的遍历区间. 但是,如果树插入的值一直递增/ ...
- UI单据按钮点击事件校验
一.按钮点击前事务处理<BeforeEventProcess> public override void BeforeEventProcess(IPart part, string eve ...
- DS DI ES SI等等
DS is called data segment register. It points to the segment of the data used by the running program ...