新增资产

现在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的更多相关文章

  1. CMDB资产管理

    .传统运维和自动化运维的区别: 传统运维: 1.项目上线: a.产品经理前期调研(需求分析) b.和开发进行评审 c.开发进行开发 d.测试进行测试 e.交给运维人员进行上线 上线: 直接将代码交给运 ...

  2. Python学习路程CMDB

    本节内容 浅谈ITIL CMDB介绍 Django自定义用户认证 Restful 规范 资产管理功能开发 浅谈ITIL TIL即IT基础架构库(Information Technology Infra ...

  3. 构建CMDB的一些启发

    开篇感言: 自从学习python自动化开发以来,一直都是从技术的角度来看待一切.以为技术就是王道.但显然我是一只井底之蛙.其实技术只不过是实现功能的工具而已,仅此而已.后来学习了解CMDB,越来越发现 ...

  4. Python之路,Day19 - CMDB、CMDB、CMDB

    Python之路,Day19 - CMDB.CMDB.CMDB   本节内容 浅谈ITIL CMDB介绍 Django自定义用户认证 Restful 规范 资产管理功能开发 浅谈ITIL TIL即IT ...

  5. python运维开发(二十五)---cmdb开发

    内容目录: 浅谈ITIL CMDB介绍 Django自定义用户认证 Restful 规范 资产管理功能开发 浅谈ITIL TIL即IT基础架构库(Information Technology Infr ...

  6. Django:之CMDB资源系统

    渐谈CMDB需要内容,ITIL.CMDB介绍.Django自定义用户认证.Restful规范.资产管理功能开发. ITIL介绍 TIL即IT基础架构库(Information Technology I ...

  7. CMDB运维开发项目

    ITIL:Information Technology Infrastructure Library 信息技术基础架构库,主要适用于IT服务管理(ITSM).ITIL为企业的IT服务管理实践提供了一个 ...

  8. CMDB项目开发

    CMDB介绍 CMDB --Configuration Management Database 配置管理数据库, CMDB存储与管理企业IT架构中设备的各种配置信息,它与所有服务支持和服务交付流程都紧 ...

  9. CMDB资产管理系统开发【day25】:需求分析

    本节内容 浅谈ITIL CMDB介绍 Django自定义用户认证 Restful 规范 资产管理功能开发 浅谈ITIL TIL即IT基础架构库(Information Technology Infra ...

随机推荐

  1. matlab学习笔记12_3串联结构体,按属性创建含有元胞数组的结构体,filenames,isfield,isstruct,orderfields

    一起来学matlab-matlab学习笔记12 12_3 结构体 串联结构体,按属性创建含有元胞数组的结构体,filenames,isfield,isstruct,orderfields 觉得有用的话 ...

  2. PMP ITTO工具

    整合管理 范围管理 进度管理 成本管理 质量 资源管理 沟通管理 风险管理 采购管理 相关方管理

  3. Superset配置mysql数据源

    1.添加mysql数据源 测试连接的时候遇到 No module named 'MySQLdb'" 安装mysqlclient pip install mysqlclient 如果遇到 ER ...

  4. StandardServer.await: Invalid command '' received

    tomcat服务运行时 后台提输出警告:StandardServer.await: Invalid command '' received 这个警告是 多个tomcat启动时会出现端口占用的情况, 将 ...

  5. 在日志中记录Java异常信息的正确姿势

    遇到的问题 今天遇到一个线上的BUG,在执行表单提交时失败,但是从程序日志中看不到任何异常信息. 在Review源代码时发现,当catch到异常时只是输出了e.getMessage(),如下所示: l ...

  6. 简单工厂(三)——JDK源码中的简单工厂

    private static Calendar createCalendar(TimeZone zone,Locale aLocale) { CalendarProvider provider = L ...

  7. Promise.resolve解析

    总结自:https://blog.csdn.net/lq15310444798/article/details/81275278 Promise.resolve返回一个Promise实例 参数分4种情 ...

  8. axios get,post请求时带headers

    axios post请求时带headers: axios.post("http://xxx.com/xxx/xxx/xxx?", { 'queslistid': this.kemu ...

  9. 【C/C++开发】C++11的模板类型判断——std::is_same和std::decay

    C++11的模板类型判断--std::is_same和std::decay 问题提出:有一个模板函数,函数在处理int型和double型时需要进行特殊的处理,那么怎么在编译期知道传入的参数的数据类型是 ...

  10. socket-02

    # -- coding: utf-8 -- _author__ = "HuaQiang Yan" import socket def handle_request(client): ...