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验证

相关文章
相关标签/搜索