采集模块继续完善
通过上一篇的采集模块,大差不差的快要完成了。
根据高内聚低耦合的开发原则,启动文件应该是就写一个run方法就好才对,于是优化了一下。
start.py
from src.script import run
if __name__ == '__main__':
run()
script.py
from lib.config.settings import settings
from src.client import Agent,SSHSalt
def run():
#判断配置文件设置的是哪种采集方式,一共三种,第一种就是agent模式,第二种和第三种因为都需要hostname而且步骤相似,于是整合成了一个方法。
if settings.MODE == 'agent':
Agent().collect()
else:
SSHSalt().collect()
client.py
from src.plugins import Plugins_Dict
from lib.config.settings import settings
import requests
class Agent():
def collect(self):
#### 采集资产信息
#这就是上一篇博客的内容了,执行每一个插件,也就是每一个设备的process方法。
res = Plugins_Dict().execute()
for k, v in res.items():
print(k, v)
#### 将采集到的信息数据发送给API端,下面两种方式发送都可以
# requests.post(settings.API_URL, data=json.dumps(res))
requests.post(settings.API_URL, json=res)
class SSHSalt():
#这个方法是用来向api发送请求,获取主机名列表的,下面会有api端的代码
def getHostname(self):
hostnames = requests.get(settings.API_URL)
### hostnames 就是获取的主机名列表
# return ['c1.com', 'c2.com']
return hostnames ### ['c1.com', 'c2.com']
def task(self, hostname):
res = Plugins_Dict(hostname=hostname).execute()
#每次的执行结果都发送给api
requests.post(settings.API, json=res)
def collect(self):
#获取了主机名列表,也就是域名
hostnames = self.getHostname()
#因为需要连接服务器,会非常耗时,所以用多线程,用线程池来实现。
from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor
p = ThreadPoolExecutor(10)
for hostname in hostnames:
p.submit(self.task, hostname)
api端,暂时就这样,还没写。
from django.shortcuts import render,HttpResponse
# Create your views here.
def asset(request):
if request.method == 'POST':
print(request.body)
return HttpResponse('okokok')
else:
#### 从数据库中获取服务器的主机名
#### 最终将数据库中存的主机名以列表的格式返回
return HttpResponse(['c1.com', 'c2.com'])
2.数据表设计
2.1 服务端app设计
- myapi : 负责接收客户端数据, 然后分析客户端数据
- backend: 后台管理的app
- respositoy : 专门负责 管理 数据模型的
2.2. 数据表设计
遵守的原则:
- 客户端采集的字段,和表的字段要一致,方便后续数据直接存储数据库
- 客户端的字段名,在数据表中也是要有的
表与表的关系:
产品表和服务器表的关系:
如果你认为是一对多:
一条产品线(王者荣耀) 跑在 100 台服务器上 , 而每一台服务器上 只跑一个业务 王
者荣耀
如果你认为是多对多:
一条产品线(王者荣耀) 跑在 100 台服务器上 , 而每一台服务器上 不只跑一个业务
王者荣耀
具体要看公司的情况而定
数据表模型设计的原则:
- 表和表之间的关系
- 表的字段 因为 客户端传过来的字段是啥 我们就要设计这些字段
from django.db import models
class UserProfile(models.Model):
"""
用户信息
"""
name = models.CharField(u'姓名', max_length=32)
email = models.EmailField(u'邮箱')
phone = models.CharField(u'座机', max_length=32)
mobile = models.CharField(u'手机', max_length=32)
password = models.CharField(u'密码', max_length=64)
class Meta:
verbose_name_plural = "用户表"
def __str__(self):
return self.name
class UserGroup(models.Model):
"""
用户组
"""
name = models.CharField(max_length=32, unique=True)
users = models.ManyToManyField('UserProfile')
class Meta:
verbose_name_plural = "用户组表"
def __str__(self):
return self.name
class BusinessUnit(models.Model):
"""
业务线
"""
name = models.CharField('业务线', max_length=64, unique=True)
contact = models.ForeignKey('UserGroup', verbose_name='业务联系人', related_name='c', on_delete=models.CASCADE)
manager = models.ForeignKey('UserGroup', verbose_name='系统管理员', related_name='m', on_delete=models.CASCADE)
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 Tag(models.Model):
"""
资产标签
"""
name = models.CharField('标签', max_length=32, unique=True)
class Meta:
verbose_name_plural = "标签表"
def __str__(self):
return self.name
class Server(models.Model):
"""
服务器信息
"""
device_type_choices = (
(1, '服务器'),
(2, '交换机'),
(3, '防火墙'),
)
device_status_choices = (
(1, '上架'),
(2, '在线'),
(3, '离线'),
(4, '下架'),
)
device_type_id = models.IntegerField('服务器类型',choices=device_type_choices, default=1)
device_status_id = models.IntegerField('服务器状态',choices=device_status_choices, default=1)
cabinet_num = models.CharField('机柜号', max_length=30, null=True, blank=True)
cabinet_order = models.CharField('机柜中序号', max_length=30, null=True, blank=True)
idc = models.ForeignKey('IDC', verbose_name='IDC机房', null=True, blank=True, on_delete=models.CASCADE)
business_unit = models.ForeignKey('BusinessUnit', verbose_name='属于的业务线', null=True, blank=True, on_delete=models.CASCADE)
tag = models.ManyToManyField('Tag')
hostname = models.CharField('主机名',max_length=128, unique=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)
manage_ip = models.GenericIPAddressField('管理IP', null=True, blank=True)
os_platform = models.CharField('系统', max_length=16, null=True, blank=True)
os_version = models.CharField('系统版本', max_length=16, 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)
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=32)
capacity = models.CharField('磁盘容量GB', max_length=32)
pd_type = models.CharField('磁盘类型', max_length=32)
server_obj = models.ForeignKey('Server',related_name='disk', 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_obj = models.ForeignKey('Server',related_name='nic', 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_obj = models.ForeignKey('Server',related_name='memory', on_delete=models.CASCADE)
class Meta:
verbose_name_plural = "内存表"
def __str__(self):
return self.slot
注:表关系图
api分析数据入库
主要以硬盘数据入库为例
from django.shortcuts import render,HttpResponse
# Create your views here.
import json
from respositoy import models
def asset(request):
if request.method == 'POST':
res = json.loads(request.body)
print(res)
#### 1.获取post过来的主机名,判断主机是否合法
status = res['basic']['status']
if status != 10000:
return HttpResponse('采集出错')
hostname = res['basic']['data']['hostname']
server_obj = models.Server.objects.filter(hostname=hostname).first()
if not server_obj:
return HttpResponse('资产未录入!')
##### 2.判断一下硬盘数据采集是否成功
code = res['disk']['status']
if code != 10000:
models.ErrorLog.objects.create(asset_obj=server_obj, content=res['disk']['data'], title='采集硬盘数据出错')
##### 3.保存磁盘的数据入库
new_disk_data = res['disk']['data']
### 新的slot集合
new_slot = list(new_disk_data.keys())
### 老的slot集合
old_disk_data = models.Disk.objects.filter(server_obj=server_obj).all()
old_slot = []
for obj in old_disk_data:
old_slot.append(obj.slot)
add_slot = set(new_slot).difference(set(old_slot)) #### [0,1,2,3,4,5]
if add_slot:
for slot in add_slot:
#### {'slot': '0', 'pd_type': 'SAS', 'capacity': '279.396', 'model': 'SEAGATE ST300MM0006 LS08S0K2B5NV'},
disk_info = res['disk']['data'][slot]
disk_info['server_obj'] = server_obj
models.Disk.objects.create(**disk_info)
return HttpResponse('okokok')
else:
#### 从数据库中获取服务器的主机名
#### 最终将数据库中存的主机名以列表的格式返回
return HttpResponse(['c1.com', 'c2.com'])