CMDB03 /今日未采集的资产、资产入库、资产变更记录、资产采集
CMDB03 /今日未采集的资产、资产入库、资产变更记录、资产采集
1. 获取今日未采集的服务器
- 代码示例: - def get(self,request,*args,**kwargs):
 """ 返回今日未采集的服务器列表 """
 today = datetime.datetime.today()
 queryset = models.Server.objects.filter(status=1).filter(Q(last_date__isnull=True)|Q(last_date__lt=today)).values('hostname')
 host_list = [ item['hostname'] for item in queryset]
 print(host_list)
 return Response(host_list)
 
2. server资产入库以及资产变更处理
- post请求代码示例 - def post(self,request,*args,**kwargs):
 # 1. 获取到用户提交资产信息
 # 2. 保存到数据库(表关系)
 hostname = request.data.get('hostname')
 server_object = models.Server.objects.filter(hostname=hostname).first()
 if not server_object:
 return Response('主机不存在')
 process_server_info(request.data['info'],server_object) # 今日已经采集
 server_object.last_date = datetime.datetime.today()
 server_object.save() return Response('发送成功')
 
- plugins / - __init__.py执行process_server_info函数,对接收到的消息做相应的处理- 代码示例: - import importlib
 from django.conf import settings
 def process_server_info(info,server_object):
 """ 处理中控汇报资产信息 """
 for key,path in settings.CMDB_PLUGIN_DICT.items():
 module_path,class_name = path.rsplit('.',maxsplit=1)
 module = importlib.import_module(module_path)
 instance = getattr(module,class_name)()
 instance.process(info[key],server_object)
 
- 判断做何处理/新增/删除/变更 - class Disk(object): def process(self,disk,server_object):
 if not disk['status']:
 print('采集资产错误',disk['error'])
 return
 disk_info = disk['data']
 new_disk_slot_set = set(disk_info.keys())
 # [obj,obj]
 db_disk_queryset = models.Disk.objects.filter(server=server_object)
 db_disk_dict = {obj.slot: obj for obj in db_disk_queryset}
 db_disk_slot_set = set(db_disk_dict.keys()) record_msg_list = [] # 新增的槽位集合
 create_slot_set = new_disk_slot_set - db_disk_slot_set
 create_object_list = []
 for slot in create_slot_set:
 # models.Disk.objects.create(**disk_info[slot],server=server_object)
 create_object_list.append(models.Disk(**disk_info[slot], server=server_object))
 if create_object_list:
 models.Disk.objects.bulk_create(create_object_list, batch_size=10)
 msg = "【新增硬盘】在%s槽位新增了硬盘。" % ",".join(create_slot_set)
 record_msg_list.append(msg) # 要删除的槽位集合
 remove_slot_set = db_disk_slot_set - new_disk_slot_set # (1,2)
 models.Disk.objects.filter(server=server_object, slot__in=remove_slot_set).delete()
 if remove_slot_set:
 msg = "【删除硬盘】在%s槽位删除了硬盘。" % ",".join(remove_slot_set)
 record_msg_list.append(msg) # 要更新的槽位集合(可能有也可能没有)
 update_slot_set = new_disk_slot_set & db_disk_slot_set
 for slot in update_slot_set:
 temp = []
 row_dict = disk_info[slot] # {'slot': '0', 'pd_type': 'SAS', 'capacity': '100', 'model': 'SEAGATE ST300MM0006 LS08S0K2B5NV'}
 row_object = db_disk_dict[slot] # row_object.slot/ row_object.pd_type = getattr(row_object,'pd_type') / row.capacity /row.model
 for key, value in row_dict.items():
 if value != getattr(row_object, key):
 msg = "%s由%s变更为%s" % (key, getattr(row_object, key), value)
 temp.append(msg)
 setattr(row_object, key, value)
 if temp:
 slot_msg = "【更新硬盘】槽位%s:%s" % (slot, " ".join(temp))
 record_msg_list.append(slot_msg)
 row_object.save() if record_msg_list:
 models.Record.objects.create(server=server_object, content="\n".join(record_msg_list))
 
3. client基于ssh远程资产采集
- app.py -- 资产采集入口 - from concurrent.futures import ThreadPoolExecutor
 from lib.plugins import get_server_info
 import settings
 import requests def ssh(hostname,command):
 import paramiko
 private_key = paramiko.RSAKey.from_private_key_file(settings.SSH_PRIVATE_KEY_PATH)
 ssh = paramiko.SSHClient()
 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
 ssh.connect(hostname=hostname, port=settings.SSH_PORT, username=settings.SSH_USER, pkey=private_key)
 stdin, stdout, stderr = ssh.exec_command(command)
 result = stdout.read()
 ssh.close()
 return result.decode('utf-8') def salt(hostname,command):
 import subprocess
 cmd = "salt '%s' cmd.run '%s' " %(hostname,command)
 data = subprocess.getoutput(cmd)
 return data def task(hostname): if settings.MODE == 'SSH':
 info = get_server_info(hostname, ssh)
 elif settings.MODE == 'SALT':
 info = get_server_info(hostname, salt)
 else:
 raise Exception('模式输入错误,请修改') requests.post(
 url="http://192.168.16.64:8000/api/v1/server/",
 json={'hostname':hostname,'info':info}
 ) def run():
 response = requests.get(url="http://192.168.16.64:8000/api/v1/server/")
 host_list = response.json()
 pool = ThreadPoolExecutor(settings.THREAD_POOL_SIZE)
 for host in host_list: # 100服务器
 pool.submit(task,host) if __name__ == '__main__':
 run()
 
- plugins / - __init__.py执行process_server_info函数,去采集相应的资产信息- from settings import PLUGIN_DICT def get_server_info(hostname,ssh_func):
 """ :param hostname: 要远程操作的主机名
 :param ssh_func: 执行远程操作的方法
 :return:
 """
 info_dict = {} for key, path in PLUGIN_DICT.items():
 module_path, class_name = path.rsplit('.', maxsplit=1) # 1. 根据字符串的形式去导入模块 "lib.plugins.board"
 import importlib
 module = importlib.import_module(module_path) # 2.去模块找到类
 cls = getattr(module, class_name) # 3. 对类型实例化
 obj = cls() # 4. 执行对象的process方法
 result = obj.process(hostname,ssh_func) info_dict[key] = result return info_dict
 
- 采集CPU信息示例 - import traceback
 from lib.log import logger
 import settings from .base import BasePlugin class CPU(BasePlugin):
 def process(self,hostname,ssh_func):
 info = {'status': True, 'data': None, 'error': None}
 try:
 if settings.DEBUG:
 with open('files/cpuinfo.out',mode='r',encoding='utf-8') as f:
 content = f.read()
 else:
 content = ssh_func(hostname, 'cat /proc/cpuinfo')
 data = self.parse(content)
 info['data'] = data
 except Exception as e:
 # 记录日志
 msg = traceback.format_exc()
 logger.log(msg)
 info['status'] = False
 info['error'] = msg
 return info def parse(self,content):
 """
 解析shell命令返回结果
 :param content: shell 命令结果
 :return:解析后的结果
 """
 response = {'cpu_count': 0, 'cpu_physical_count': 0, 'cpu_model': ''} cpu_physical_set = set() content = content.strip()
 for item in content.split('\n\n'):
 for row_line in item.split('\n'):
 value_list = row_line.split(':')
 if len(value_list) !=2:
 continue
 key,value = value_list
 key = key.strip()
 if key == 'processor':
 response['cpu_count'] += 1
 elif key == 'physical id':
 cpu_physical_set.add(value)
 elif key == 'model name':
 if not response['cpu_model']:
 response['cpu_model'] = value
 response['cpu_physical_count'] = len(cpu_physical_set) return response
 
- log.py -- 用来记录异常日志 - import logging
 import settings class AutoLogger(object):
 def __init__(self,log_path,log_name):
 file_handler = logging.FileHandler(log_path, 'a', encoding='utf-8')
 fmt = logging.Formatter(fmt="%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s")
 file_handler.setFormatter(fmt) self.logger = logging.Logger(log_name, level=logging.DEBUG)
 self.logger.addHandler(file_handler) def log(self,msg):
 self.logger.error(msg) logger = AutoLogger(settings.LOG_FILE_PATH,'cmdb')
 
总结:
- 对于今日未采集的服务器采用了基于Q实现复杂的SQL查询
- 对于变更处理采用集合的交集、差集,进而进行判断
- 中控机汇报到api的资产需要做入库以及变更记录的处理
- 由于资产搜集时是利用工厂模式实现可扩展插件,方便于扩展。在api端也是使用相同模式,对插件进行一一处理。
- 在处理资产信息时候,对操作进行交集和差集的处理从而得到删除/更新/新增资产。
- 在内部通过反射进行资产变更记录的获取,最终将资产以及变更记录写入数据库。
 
CMDB03 /今日未采集的资产、资产入库、资产变更记录、资产采集的更多相关文章
- CMDB服务器管理系统【s5day90】:获取今日未采集主机列表
		1.目录结构 1.服务器端 2.客户端 2.具体代码如下 1.数据库增加两个字段 class Server(models.Model): """ 服务器信息 " ... 
- python-cmdb资产管理项目4-资产入库处理以及资产变更记录处理
		一 资产入库处理 1.1 连接数据库 在192.168.100.101安装数据库,并给总控机授权可以操作,并创建一个autoserver的数据库,密码123456 settiing.py 配置数据库连 ... 
- WEB页面采集器编写经验之一:静态页面采集器
		严格意义来说,采集器和爬虫不是一回事:采集器是对特定结构的数据来源进行解析.结构化,将所需的数据从中提取出来:而爬虫的主要目标更多的是页面里的链接和页面的TITLE. 采集器也写过不少了,随便写一点经 ... 
- ThinkPHP Http工具类(用于远程采集 远程下载)      phpSimpleHtmlDom采集类库_Jquery筛选方式   使用phpQuery轻松采集网页内容http://www.thinkphp.cn/extend/541.html
		[php]代码库 view sourceprint? <?php // +------------------------------------------------------------ ... 
- Java版基于SpringBoot+Vue.js实现自动创表自动定时采集(各个微信公众号商城产品进行采集)-爬虫篇
- CMDB资产采集方案
		CMDB资产采集方案 CMDB 资产采集的方案总共有四种 Agent SSH类 Saltstack Puttet 方案设计,从性能上考虑 下面前三种是用Python开发的,目标是兼容三种采集方式的软件 ... 
- CMDB资产采集笔记
		一.资产采集四种方式 1. Agent方式 API:Django接收数据并入库 程序:放置在每台服务器 应用场景:针对服务器较多的公司 步骤一: #执行本地命令的库 import subprocess ... 
- CMDB资产采集方式
		一:Agent方式 原理:在每台服务器装上agent客户端程序,定时向数据库发送指定的资产信息. 优点:速度快. 缺点:服务器上需要多装一个软件 import subprocess import re ... 
- Django项目:CMDB(服务器硬件资产自动采集系统)--12--08CMDB采集硬件数据日志记录
		#settings.py # ————————01CMDB获取服务器基本信息———————— import os BASEDIR = os.path.dirname(os.path.dirname(o ... 
随机推荐
- Java复习目录
			还是寒假用了十多天的时间在b站把基础部分学习完了,现在刚开学开始上Java课,以博客的方式复习前面学习的内容. 总结: ①吸取前面MySQL学习的教训,每天固定学习的内容,学习效果很有提升,但临近开学 ... 
- flutter-web利用dart js 库发起http request
			初学flutter,初学前端,尝试在dart中直接使用HttpClient时,直接报出Platform not supported,查资料发现他还不支持浏览器. 通过查阅资料发现可以借助axios 与 ... 
- 使用Java代码配置MyBatis Generator
			使用MyBatis Generator生成器时,有时候没办法使用xml型的配置文件,比如将Maven项目设置成pom打包方式(<packaging>pom</packaging> ... 
- 附024.Kubernetes全系列大总结
			Kubernetes全系列总结如下,后期不定期更新.欢迎基于学习.交流目的的转载和分享,禁止任何商业盗用,同时希望能带上原文出处,尊重ITer的成果,也是尊重知识.若发现任何错误或纰漏,留言反馈或右侧 ... 
- python学习日记2019.9.2
			1 定义一个字符串对象str str.title() #将字符串中用空格分隔的字符段首字母大写 str.rstrip() #将字符串末的空格删去 str.strip() #将字符串首末的空格删去 st ... 
- Git 居然可以用来跟女神聊天?
			Git 是用来做啥的?想必码农朋友都知道,Git 是版本控制软件,是软件开发过程中团队协作不可或缺的软件. 但是,作为版本控制软件的 Git ,能跟聊天工具扯上关系吗?这二者似乎毫无关系,但脑洞大开的 ... 
- vue开发搭建(npm安装 + vue脚手架安装)
			一.概念 1.npm: Nodejs下的包管理器. 2.webpack: 它主要的用途是通过CommonJS的语法,把所有浏览器端需要发布的静态资源,做相应的准备,比如资源的合并和打包. 3.vue ... 
- weblogic之高级进阶JMS的应用
			不仅Activemq提供的jms服务,Weblogic也提供了jms服务,很多项目是部署在Weblogic中,使用其提供的jms服务也是很多企业的选择,一直没亲手试过,今天试了下,遇到的小问题还挺多, ... 
- ThinkPHP5使用PHPExcel实现数据导出功能
			1.将PHPExcel类库文件夹放入extend目录下 2.导出功能实现 public function download(){ if(request()->isPost()){ $val = ... 
- git push和pull如何解决冲突!!!精品
			多人合作完成项目时,git push 和 pull经常会发生冲突,根本原因就是远程的东西和本地的东西长的不一样,以下步骤能完美解决所有冲突!(先查看一下分支(git branch),确认没错再进行下面 ... 
